From 845552e2759be3fa4e4a803739956ab1cf5eaf8a Mon Sep 17 00:00:00 2001 From: Daniel van der Schuur <schuur@astron.nl> Date: Wed, 6 Jan 2021 14:20:26 +0100 Subject: [PATCH] -Replaced st_histogram.vhd contents with cleaned version --- .../dsp/st/src/vhdl/mms_st_histogram.vhd | 6 +- libraries/dsp/st/src/vhdl/st_histogram.vhd | 896 ++++-------------- libraries/dsp/st/tb/vhdl/tb_st_histogram.vhd | 12 +- 3 files changed, 180 insertions(+), 734 deletions(-) diff --git a/libraries/dsp/st/src/vhdl/mms_st_histogram.vhd b/libraries/dsp/st/src/vhdl/mms_st_histogram.vhd index 8472efc407..0ab6ae546e 100644 --- a/libraries/dsp/st/src/vhdl/mms_st_histogram.vhd +++ b/libraries/dsp/st/src/vhdl/mms_st_histogram.vhd @@ -97,9 +97,9 @@ BEGIN dp_rst => dp_rst, dp_clk => dp_clk, - snk_in => snk_in, - sla_in_ram_mosi => ram_st_histogram_mosi, - sla_out_ram_miso => ram_st_histogram_miso + snk_in => snk_in +-- sla_in_ram_mosi => ram_st_histogram_mosi, +-- sla_out_ram_miso => ram_st_histogram_miso ); u_st_histogram_reg : ENTITY work.st_histogram_reg diff --git a/libraries/dsp/st/src/vhdl/st_histogram.vhd b/libraries/dsp/st/src/vhdl/st_histogram.vhd index 13b57e0ee1..c2c117e390 100644 --- a/libraries/dsp/st/src/vhdl/st_histogram.vhd +++ b/libraries/dsp/st/src/vhdl/st_histogram.vhd @@ -18,68 +18,10 @@ -- ------------------------------------------------------------------------------- -------------------------------------------------------------------------------- --- --- Author: J.W.E. Oudman --- Purpose: Create a histogram from the input data and present it to --- st_histogram_reg --- 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 3 --- cycles. While one RAM block is used to count the input samples, the other --- is read by the MM bus through st_histogram_reg. --- --- --- ram_pointer ram_pointer --- | | --- | /o--- RAM_0 ---o | --- |/ | --- / | --- snk_in ----o/ | /o----- ram_miso (st_histogram_reg) --- |/ _mosi --- / --- 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. --- If the MM bus needs to acces the data in a RAM block it has to acces it --- through st_histogram_reg as the mm_clk can't be used. --- --- The design is basically devided in the following blocks of code: --- . Assign inputs of RAM --- . Bin reader --- . Bin Writer --- . Bin Arbiter --- . RAM selector & Dual swapped RAM instances --- . Connect interface to DUAL swapped RAM, read out histogram statistics --- --- 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 2 cycles to receive it's value and --- another cycle before the calculated value can be written into that RAM --- adress (1st cycle: address; 3rd cycle: data available; 5th cycle: write --- data). 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 (missing samples) and writing takes priority --- in this case --- . When a sync signal appears the RAM has to be swapped 4 cycles later so --- the first 3 cycles may/can not ask a read from the old RAM block (the --- read_enable takes one cycle hence the difference of 3 against 4 cycles) --- -------------------------------------------------------------------------------- + +-- Author: Daniel van der Schuur +-- Purpose: + LIBRARY IEEE, common_lib, mm_lib, technology_lib, dp_lib; USE IEEE.std_logic_1164.ALL; @@ -89,705 +31,209 @@ USE dp_lib.dp_stream_pkg.ALL; USE technology_lib.technology_select_pkg.ALL; ENTITY st_histogram IS - GENERIC ( - g_in_data_w : NATURAL := 14; -- >= 9 when g_nof_bins is 512; (max. c_dp_stream_data_w =768) <-- maybe just g_data_w ?? - g_nof_bins : NATURAL := 512; -- is a power of 2 and g_nof_bins <= c_data_span; max. 512 - g_nof_data : NATURAL; -- - g_str : STRING := "freq.density"; -- to select output to MM bus ("frequency" or "freq.density") - g_ram_miso_sim_mode : BOOLEAN := FALSE -- when TRUE the ram_miso bus will get a copy of the data written into the RAM. - ); PORT ( dp_rst : IN STD_LOGIC; dp_clk : IN STD_LOGIC; - -- Streaming - snk_in : IN t_dp_sosi; - - -- DP clocked memory bus - sla_in_ram_mosi : IN t_mem_mosi; -- Beware, works in dp clock domain ! - sla_out_ram_miso : OUT t_mem_miso; -- '' ! --- ram_mosi : IN t_mem_mosi; -- Beware, works in dp clock domain ! --- ram_miso : OUT t_mem_miso -- '' ! - -- Debug bus - dbg_ram_miso : OUT t_mem_miso + snk_in : IN t_dp_sosi ); END st_histogram; ARCHITECTURE rtl OF st_histogram IS --- 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_clear : NATURAL := g_nof_data - g_nof_bins; - 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; >= 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 - --- CONSTANT c_mem_miso_setting : t_mem_miso := (rddata => mem_miso_init, -- c_mem_miso_rst; -- limit to 32 bit --- rdval => '0', --- waitrequest => '0' ); - --- SIGNAL mem_miso_init : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0) := (OTHERS => '0'); - - SIGNAL snk_in_p : t_dp_sosi; - SIGNAL snk_in_pp : t_dp_sosi; - SIGNAL snk_in_pppp : t_dp_sosi; - - SIGNAL bin_reader_mosi : t_mem_mosi := c_mem_mosi_rst; - SIGNAL prev_bin_reader_mosi : t_mem_mosi := c_mem_mosi_rst; - SIGNAL bin_reader_mosi_pp : t_mem_mosi := c_mem_mosi_rst; - SIGNAL bin_reader_mosi_ppp : t_mem_mosi := c_mem_mosi_rst; - - SIGNAL nxt_bin_writer_mosi : t_mem_mosi; - SIGNAL bin_writer_mosi : t_mem_mosi; + CONSTANT c_nof_bins : NATURAL := 256; + CONSTANT c_in_data_w : NATURAL := 8; + CONSTANT c_adr_low : NATURAL := c_in_data_w-8; -- 0 + + ------------------------------------------------------------------------------- + -- bin_reader + ------------------------------------------------------------------------------- + SIGNAL bin_reader_mosi : t_mem_mosi; + SIGNAL bin_reader_miso : t_mem_miso; + + SIGNAL prv_rd_address : STD_LOGIC_VECTOR(32-1 DOWNTO 0); + + ------------------------------------------------------------------------------- + -- bin_writer + ------------------------------------------------------------------------------- + SIGNAL bin_reader_to_writer_mosi : t_mem_mosi; + + SIGNAL nxt_bin_writer_mosi : t_mem_mosi; + SIGNAL bin_writer_mosi : t_mem_mosi; + + ------------------------------------------------------------------------------- + -- bin_arbiter + ------------------------------------------------------------------------------- + SIGNAL write_allowed : BOOLEAN; SIGNAL nxt_bin_arbiter_wr_mosi : t_mem_mosi; SIGNAL bin_arbiter_wr_mosi : t_mem_mosi; - - SIGNAL nxt_bin_arbiter_rd_mosi : t_mem_mosi; SIGNAL bin_arbiter_rd_mosi : t_mem_mosi; + SIGNAL bin_arbiter_rd_miso : t_mem_miso; + + ------------------------------------------------------------------------------- + -- 2x RAM (common_ram_r_w) instances + ------------------------------------------------------------------------------- + CONSTANT c_nof_common_ram_r_w : NATURAL := 2; + + CONSTANT c_adr_w : NATURAL := ceil_log2(c_nof_bins); + CONSTANT c_ram : t_c_mem := (latency => 1, + adr_w => c_adr_w, -- 8 bits needed to adress/select 256 adresses + dat_w => c_word_w, -- 32b, def. in common_pkg; >= c_bin_w + nof_dat => c_nof_bins, -- 256 adresses with 32b words + init_sl => '0'); + + SIGNAL ram_pointer : STD_LOGIC; - SIGNAL bin_arbiter_rd_miso : t_mem_miso := c_mem_miso_rst; - SIGNAL bin_reader_rd_miso : t_mem_miso := c_mem_miso_rst; - SIGNAL common_ram_r_w_miso : t_mem_miso := c_mem_miso_rst; - - SIGNAL init_phase : STD_LOGIC := '1'; - SIGNAL nxt_init_phase : STD_LOGIC; - - SIGNAL rd_cnt_allowed : STD_LOGIC := '0'; - SIGNAL rd_cnt_allowed_pp : STD_LOGIC := '0'; - - SIGNAL toggle_detect : STD_LOGIC := '0'; - SIGNAL toggle_detect_pp : STD_LOGIC; - SIGNAL toggle_detect_false : STD_LOGIC := '1'; - SIGNAL nxt_toggle_detect_false : STD_LOGIC; - - SIGNAL nxt_prev_wrdata : NATURAL; - SIGNAL prev_wrdata : NATURAL; - SIGNAL prev_prev_wrdata : NATURAL; - SIGNAL prev_prev_prev_wrdata : NATURAL; - - SIGNAL sync_detect : STD_LOGIC := '0'; - SIGNAL sync_detect_pp : STD_LOGIC; - - SIGNAL same_r_w_address : STD_LOGIC; - SIGNAL same_r_w_address_pp : STD_LOGIC; - - --debug signals - SIGNAL dbg_state_string : STRING(1 TO 3) := " "; - SIGNAL dbg_snk_data : STD_LOGIC_VECTOR(g_in_data_w-1 DOWNTO 0); - - - SIGNAL ram_pointer : STD_LOGIC := '0'; - SIGNAL cycle_cnt : NATURAL := 0 ; - SIGNAL nxt_cycle_cnt : NATURAL := 0 ; --- SIGNAL wr_en : STD_LOGIC := '0'; --- SIGNAL nxt_wr_en : STD_LOGIC; --- SIGNAL wr_dat : STD_LOGIC_VECTOR(c_word_w -1 DOWNTO 0); --- SIGNAL nxt_wr_dat : STD_LOGIC_VECTOR(c_word_w -1 DOWNTO 0); --- SIGNAL wr_adr : STD_LOGIC_VECTOR(g_in_data_w -1 DOWNTO c_adr_low); --- SIGNAL rd_adr : STD_LOGIC_VECTOR(g_in_data_w -1 DOWNTO c_adr_low); --- SIGNAL rd_en : STD_LOGIC := '0'; --- SIGNAL rd_dat : STD_LOGIC_VECTOR(c_word_w -1 DOWNTO 0); --- SIGNAL rd_val : STD_LOGIC; - - SIGNAL mm_adr_cnt : NATURAL := 0 ; - SIGNAL mm_adr_illegal : STD_LOGIC := '0'; - SIGNAL mm_adr_illegal_pp : STD_LOGIC := '0'; - - - SIGNAL ram_0_wr_en : STD_LOGIC; - SIGNAL ram_0_wr_dat : STD_LOGIC_VECTOR(c_word_w -1 DOWNTO 0); - SIGNAL ram_0_wr_adr : STD_LOGIC_VECTOR(g_in_data_w -1 DOWNTO c_adr_low); - SIGNAL ram_0_rd_adr : STD_LOGIC_VECTOR(g_in_data_w -1 DOWNTO c_adr_low); - SIGNAL ram_0_rd_en : STD_LOGIC; - SIGNAL ram_0_rd_dat : STD_LOGIC_VECTOR(c_word_w -1 DOWNTO 0); - SIGNAL ram_0_rd_val : STD_LOGIC; - - SIGNAL ram_1_wr_en : STD_LOGIC; - SIGNAL ram_1_wr_dat : STD_LOGIC_VECTOR(c_word_w -1 DOWNTO 0); - SIGNAL ram_1_wr_adr : STD_LOGIC_VECTOR(g_in_data_w -1 DOWNTO c_adr_low); - SIGNAL ram_1_rd_adr : STD_LOGIC_VECTOR(g_in_data_w -1 DOWNTO c_adr_low); - SIGNAL ram_1_rd_en : STD_LOGIC; - SIGNAL ram_1_rd_dat : STD_LOGIC_VECTOR(c_word_w -1 DOWNTO 0); - SIGNAL ram_1_rd_val : STD_LOGIC; - - SIGNAL ram_out_wr_en : STD_LOGIC; - SIGNAL ram_out_wr_dat : STD_LOGIC_VECTOR(c_word_w -1 DOWNTO 0); - SIGNAL ram_out_wr_adr : STD_LOGIC_VECTOR(g_in_data_w -1 DOWNTO c_adr_low); - SIGNAL ram_out_rd_adr : STD_LOGIC_VECTOR(g_in_data_w -1 DOWNTO c_adr_low); - SIGNAL ram_out_rd_en : STD_LOGIC; - SIGNAL ram_out_rd_dat : STD_LOGIC_VECTOR(c_word_w -1 DOWNTO 0); - SIGNAL ram_out_rd_val : STD_LOGIC; - - SIGNAL prev_ram_out_wr_adr : STD_LOGIC_VECTOR(g_in_data_w -1 DOWNTO c_adr_low); - SIGNAL ram_out_same_w_r_adr : STD_LOGIC; - -BEGIN - - ----------------------------------------------------------------------------- - -- Check Generics - ----------------------------------------------------------------------------- - 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 RAM: <-- use parts of description for bin_writer - -- . Determine address based on input data - -- . 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 a local 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 data to be written . - -- at the next cycle by making nxt_wr_en high . - -- . Write the wr_dat data to the RAM - -- . At the snk_in.sync pulse: - -- . let first 3 cycles start counting from 0 again - -- . (plus 3 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 - -- - -- - -- . in : snk_in (latency: 0) - -- : common_ram_r_w_miso (latency: 2) - -- . out : snk_in_pppp.sync (latency: 4) - -- : bin_arbiter_wr_mosi (latency: 4) - -- : bin_arbiter_rd_mosi (latency: 1) - -- - ---------------------------------------------------------------------------- - - ----------------------------------------------------------------------------- - -- Bin reader: Convert snk_in data to bin_reader_mosi with read request - -- and generate signals for detection of problems in the - -- consecutive data. - -- . in : snk_in (latency: 0) - -- : bin_arbiter_rd_miso (latency: 2) - -- . out : init_phase (latency: 0 ? - -- : bin_reader_mosi (latency: 0) - -- : prev_bin_reader_mosi (latency: 1) - -- : bin_reader_mosi_pp (latency: 2) - -- : bin_reader_mosi_ppp (latency: 3) - -- : bin_reader_rd_miso (latency: 2) - -- : rd_cnt_allowed_pp (latency: 2) - -- : same_r_w_address_pp (latency: 2) - -- : toggle_detect_pp (latency: 2) - -- : sync_detect (latency: 0) - -- : sync_detect_pp (latency: 2) - ----------------------------------------------------------------------------- - bin_reader_mosi.rd <= snk_in.valid; -- when 1, count allowed - bin_reader_mosi.address(c_adr_w-1 DOWNTO 0) <= snk_in.data(g_in_data_w-1 DOWNTO c_adr_low); - bin_reader_rd_miso <= bin_arbiter_rd_miso; - - --snk_in pipeline; Enable sync and valid comparisons - u_dp_pipeline_snk_in_1_cycle : ENTITY dp_lib.dp_pipeline - GENERIC MAP ( - g_pipeline => 1 -- 0 for wires, > 0 for registers, - ) - PORT MAP ( - rst => dp_rst, - clk => dp_clk, - snk_in => snk_in, - src_out => snk_in_p - ); - --- init_phase <= '0' WHEN snk_in_p.sync = '1'; -- ELSE will be impossible since the init_phase may only be triggered once on the first sync - nxt_init_phase <= '0' WHEN snk_in.sync='1' ELSE init_phase; - - p_init_phase : PROCESS(dp_clk, dp_rst) - BEGIN - IF dp_rst = '1' THEN - init_phase <= '1'; - toggle_detect_false <= '1'; - ELSIF RISING_EDGE(dp_clk) THEN - init_phase <= nxt_init_phase; - toggle_detect_false <= nxt_toggle_detect_false; - END IF; - END PROCESS; - - -- Enable sync comparisons - u_dp_pipeline_snk_in_2_cycle : ENTITY dp_lib.dp_pipeline - GENERIC MAP ( - g_pipeline => 2 -- 0 for wires, > 0 for registers, - ) - PORT MAP ( - rst => dp_rst, - clk => dp_clk, - snk_in => snk_in, - src_out => snk_in_pp - ); - - -- Enable switching the ram_pointer - u_dp_pipeline_snk_in_4_cycle : ENTITY dp_lib.dp_pipeline - GENERIC MAP ( - g_pipeline => 4 -- 0 for wires, > 0 for registers, - ) - PORT MAP ( - rst => dp_rst, - clk => dp_clk, - snk_in => snk_in, - src_out => snk_in_pppp - ); - - dbg_snk_data <= snk_in_pp.data(g_in_data_w-1 DOWNTO 0); - --- toggle_detect_false <= '0' WHEN snk_in_pp.sync = '1'; -- ELSE will be impossible since the toggle_detect_false may only be triggered once on the first sync - nxt_toggle_detect_false <= '0' WHEN snk_in_p.sync='1' ELSE toggle_detect_false; - sync_detect <= snk_in.valid WHEN (snk_in.sync='1' OR snk_in_p.sync='1' OR snk_in_pp.sync='1') ELSE '0'; -- @sync, first 3 cycles would try to read from the wrong (old) RAM block, detect this problem - - -- Line up to p_nxt_bin_writer_mosi process - u_common_pipeline_sl_sync_detect_2_cycle : ENTITY common_lib.common_pipeline_sl - GENERIC MAP( - g_pipeline => 2 -- 0 for wires, > 0 for registers, - ) - PORT MAP ( - clk => dp_clk, - in_dat => sync_detect, - out_dat => sync_detect_pp - ); - - -- Enable adress comparisons 1 cycle back - -- Skip unvalid data with trigger bin_reader_mosi.rd to make comparisons between unvalid-data-seperated data possible. - u_common_pipeline_bin_reader_mosi_1_cycle : ENTITY common_lib.common_pipeline - GENERIC MAP ( - g_representation => "UNSIGNED", --orig. signed - g_pipeline => 1, - g_in_dat_w => c_adr_w, -- c_mem_address_w - g_out_dat_w => c_adr_w - ) - PORT MAP ( - clk => dp_clk, - clken => bin_reader_mosi.rd, -- '1', - in_dat => STD_LOGIC_VECTOR(bin_reader_mosi.address(c_adr_w-1 DOWNTO 0)), - out_dat => prev_bin_reader_mosi.address(c_adr_w-1 DOWNTO 0) - ); - - -- Enable adress comparisons 2 cycles back - u_common_pipeline_bin_reader_mosi_2_cycle : ENTITY common_lib.common_pipeline - GENERIC MAP ( - g_representation => "UNSIGNED", --orig. signed - g_pipeline => 1, - g_in_dat_w => c_adr_w, - g_out_dat_w => c_adr_w - ) - PORT MAP ( - clk => dp_clk, - in_dat => STD_LOGIC_VECTOR(prev_bin_reader_mosi.address(c_adr_w-1 DOWNTO 0)), - out_dat => bin_reader_mosi_pp.address(c_adr_w-1 DOWNTO 0) - ); - - -- Enable adress comparisons 3 cycles back - u_common_pipeline_bin_reader_mosi_3_cycle : ENTITY common_lib.common_pipeline - GENERIC MAP ( - g_representation => "UNSIGNED", --orig. signed - g_pipeline => 2, - g_in_dat_w => c_adr_w, - g_out_dat_w => c_adr_w - ) - PORT MAP ( - clk => dp_clk, - in_dat => STD_LOGIC_VECTOR(prev_bin_reader_mosi.address(c_adr_w-1 DOWNTO 0)), - out_dat => bin_reader_mosi_ppp.address(c_adr_w-1 DOWNTO 0) - ); - - - -- Only count sequential valid data on the same address when: address is the same as last and 1 or 2 cycles after the sync when in sync_detect; address is the same as last and past the initialisation and outside sync_detect - rd_cnt_allowed <= snk_in.valid WHEN ( bin_reader_mosi.address = prev_bin_reader_mosi.address AND ( snk_in_p.sync='1' OR (snk_in_pp.sync='1' AND snk_in_p.valid='1') ) ) - OR (bin_reader_mosi.address = prev_bin_reader_mosi.address AND init_phase='0' AND sync_detect='0') - ELSE '0'; - - -- Line rd_cnt_allowed up to p_nxt_bin_writer_mosi process - u_common_pipeline_sl_rd_cnt_allowed : ENTITY common_lib.common_pipeline_sl - GENERIC MAP( - g_pipeline => 2 -- 0 for wires, > 0 for registers, - ) - PORT MAP ( - clk => dp_clk, - in_dat => rd_cnt_allowed, - out_dat => rd_cnt_allowed_pp - ); - - -- Detect a (valid) repeating address seperated by one other address past the initialisation and outside the first two cycles of a (new) sync --also @sync, one wil be true; use NOT(1 or 1) instead of (0 or 0) - toggle_detect <= snk_in.valid WHEN (bin_reader_mosi_pp.address = bin_reader_mosi.address AND bin_reader_mosi_pp.address /= prev_bin_reader_mosi.address AND toggle_detect_false = '0' AND NOT(snk_in.sync='1' OR snk_in_p.sync='1') ) - ELSE '0'; - - - -- Line up to p_nxt_bin_writer_mosi process - u_common_pipeline_sl_toggle_detect : ENTITY common_lib.common_pipeline_sl - GENERIC MAP( - g_pipeline => 2 -- 0 for wires, > 0 for registers, - ) - PORT MAP ( - clk => dp_clk, - in_dat => toggle_detect, - out_dat => toggle_detect_pp - ); - - -- Detect an (valid) address that has to be read as well as written at the same time - same_r_w_address <= snk_in.valid WHEN (bin_reader_mosi.address = bin_reader_mosi_ppp.address AND init_phase = '0' AND sync_detect = '0') ELSE '0'; - - -- Line up top p_nxt_bin_writer_mosi process - u_common_pipeline_sl_same_r_w_address : ENTITY common_lib.common_pipeline_sl - GENERIC MAP( - g_pipeline => 2 -- 0 for wires, > 0 for registers, - ) - PORT MAP ( - clk => dp_clk, - in_dat => same_r_w_address, - out_dat => same_r_w_address_pp - ); + SIGNAL common_ram_r_w_wr_mosi_arr : t_mem_mosi_arr(1 DOWNTO 0); + SIGNAL common_ram_r_w_rd_mosi_arr : t_mem_mosi_arr(1 DOWNTO 0); + SIGNAL common_ram_r_w_rd_miso_arr : t_mem_miso_arr(1 DOWNTO 0); + SIGNAL histogram_wr_mosi : t_mem_mosi; + SIGNAL histogram_rd_mosi : t_mem_mosi; + SIGNAL histogram_rd_miso : t_mem_miso; - ----------------------------------------------------------------------------- - -- Bin writer : increments current bin value and sets up write request - -- . in : toggle_detect_pp (latency: 2) - -- . in : same_r_w_address_pp (latency: 2) - -- . in : bin_reader_mosi_pp (latency: 2) - -- . in : bin_reader_rd_miso (latency: 2) aka bin_arbiter_rd_miso or common_ram_r_w_miso - -- . in : rd_cnt_allowed_pp (latency: 2) - -- . in : sync_detect_pp - -- . out : bin_writer_mosi (latency: 3) - ----------------------------------------------------------------------------- - p_nxt_bin_writer_mosi : PROCESS(bin_reader_rd_miso, - bin_reader_mosi_pp.address, toggle_detect_pp, rd_cnt_allowed_pp, prev_wrdata, prev_prev_wrdata, prev_prev_prev_wrdata, sync_detect_pp, same_r_w_address_pp) IS - BEGIN - nxt_bin_writer_mosi <= c_mem_mosi_rst; - dbg_state_string <= "unv"; - IF bin_reader_rd_miso.rdval='1' THEN - nxt_bin_writer_mosi.wr <= '1'; - nxt_bin_writer_mosi.wrdata <= INCR_UVEC(bin_reader_rd_miso.rddata, 1); - nxt_bin_writer_mosi.address <= bin_reader_mosi_pp.address; - nxt_prev_wrdata <= TO_UINT(bin_reader_rd_miso.rddata) + 1; - dbg_state_string <= "val"; - - ELSIF toggle_detect_pp = '1' THEN - nxt_bin_writer_mosi.wr <= '1'; - nxt_bin_writer_mosi.wrdata <= TO_UVEC( (prev_prev_wrdata+1), c_mem_data_w); - nxt_bin_writer_mosi.address <= bin_reader_mosi_pp.address; - nxt_prev_wrdata <= prev_prev_wrdata+1; - dbg_state_string <= "td "; - - ELSIF rd_cnt_allowed_pp = '1' THEN - nxt_bin_writer_mosi.wr <= '1'; - nxt_bin_writer_mosi.wrdata <= TO_UVEC( (prev_wrdata + 1), c_mem_data_w); - nxt_prev_wrdata <= prev_wrdata + 1; - dbg_state_string <= "r# "; - nxt_bin_writer_mosi.address <= bin_reader_mosi_pp.address; - - ELSIF sync_detect_pp = '1' THEN - nxt_bin_writer_mosi.wr <= '1'; - nxt_bin_writer_mosi.wrdata <= TO_UVEC(1, c_mem_data_w); -- snk_in.sync: 1; snk_in_p.sync (thus new adress): 1; snk_in_pp.sync (thus new adress): 1 - nxt_bin_writer_mosi.address <= bin_reader_mosi_pp.address; - nxt_prev_wrdata <= 1; - dbg_state_string <= "sd "; - - ELSIF same_r_w_address_pp = '1' THEN - nxt_bin_writer_mosi.wr <= '1'; - nxt_bin_writer_mosi.wrdata <= TO_UVEC( (prev_prev_prev_wrdata+1), c_mem_data_w); - nxt_bin_writer_mosi.address <= bin_reader_mosi_pp.address; - nxt_prev_wrdata <= prev_prev_prev_wrdata + 1; - dbg_state_string <= "srw"; - END IF; - END PROCESS; - - p_prev_wrdata : PROCESS(dp_clk, dp_rst, nxt_bin_writer_mosi.wr) IS --seperated from p_bin_writer_mosi since the implementation was unwanted +BEGIN + + ------------------------------------------------------------------------------- + -- bin_reader : reads bin from RAM, sends bin + count to bin_writer. + -- . Input : snk_in (input data stream) + -- bin_reader_miso (reply to RAM read request: rddata = bin count) + -- . Output : bin_reader_mosi (RAM read request, address = bin) + -- bin_reader_to_writer_mosi (address = bin, wrdata = bin count) + ------------------------------------------------------------------------------- + -- Fetch the bin from RAM + bin_reader_mosi.wrdata <= (OTHERS=>'0'); + bin_reader_mosi.wr <= '0'; + bin_reader_mosi.rd <= snk_in.valid; + bin_reader_mosi.address <= RESIZE_UVEC(snk_in.data(c_in_data_w-1 DOWNTO c_adr_low), 32); + + -- Store the rd address as bin_writer needs to know where to write the bin count + p_prv_rd_address : PROCESS(dp_clk, dp_rst) IS BEGIN IF dp_rst = '1' THEN - prev_wrdata <= 0; - prev_prev_wrdata <= 0; - prev_prev_prev_wrdata <= 0; - ELSIF nxt_bin_writer_mosi.wr='1' AND RISING_EDGE(dp_clk) THEN - prev_wrdata <= nxt_prev_wrdata; - prev_prev_wrdata <= prev_wrdata; - prev_prev_prev_wrdata <= prev_prev_wrdata; + prv_rd_address <= (OTHERS=>'0'); + ELSIF RISING_EDGE(dp_clk) THEN + prv_rd_address <= bin_reader_mosi.address; END IF; END PROCESS; - p_bin_writer_mosi : PROCESS(dp_clk, dp_rst) IS --, nxt_bin_writer_mosi, nxt_prev_wrdata, prev_wrdata, prev_prev_wrdata + -- Forward the read bin + count to bin writer + bin_reader_to_writer_mosi.wr <= bin_reader_miso.rdval; + bin_reader_to_writer_mosi.wrdata <= RESIZE_UVEC(bin_reader_miso.rddata(8-1 DOWNTO 0), 72); + bin_reader_to_writer_mosi.address <= prv_rd_address; + + + ------------------------------------------------------------------------------- + -- bin_writer : Increment the bin, forward write request to bin_arbiter + -- . Input : bin_reader_to_writer_mosi (from bin_reader = bin + bin count) + -- . Output : bin_writer_mosi (to bin_arbiter = bin + incremented bin count) + ------------------------------------------------------------------------------- + nxt_bin_writer_mosi.rd <= '0'; + nxt_bin_writer_mosi.wr <= bin_reader_to_writer_mosi.wr; + nxt_bin_writer_mosi.address <= bin_reader_to_writer_mosi.address; + nxt_bin_writer_mosi.wrdata <= INCR_UVEC(bin_reader_to_writer_mosi.wrdata, 1); + + -- Register the outputs to bin_arbiter (above we have a combinational adder = propagation delay) + p_bin_writer_mosi : PROCESS(dp_clk, dp_rst) IS BEGIN IF dp_rst = '1' THEN - bin_writer_mosi <= c_mem_mosi_rst; --- prev_wrdata <= 0; --- prev_prev_wrdata <= 0; --- prev_prev_prev_wrdata <= 0; + bin_writer_mosi <= c_mem_mosi_rst; ELSIF RISING_EDGE(dp_clk) THEN - bin_writer_mosi <= nxt_bin_writer_mosi; --- IF nxt_bin_writer_mosi.wr = '1' THEN --- prev_wrdata <= nxt_prev_wrdata; --- prev_prev_wrdata<= prev_wrdata; --- prev_prev_prev_wrdata <= prev_prev_wrdata; --- END IF; + bin_writer_mosi <= nxt_bin_writer_mosi; END IF; END PROCESS; - ----------------------------------------------------------------------------- - -- Bin Arbiter: Determine next RAM access - -- . in : bin_reader_mosi (latency: 0) - -- : init_phase (latency: 0) - -- : prev_bin_reader_mosi (latency: 1) - -- : bin_reader_mosi_pp (latency: 2) - -- : bin_reader_mosi_ppp (latency: 3) - -- : bin_writer_mosi (latency: 3) - -- : sync_detect (latency: 0? or 3? - -- : common_ram_r_w_miso (latency: 2) - -- . out : bin_arbiter_rd_mosi (latency: 1) - -- . : bin_arbiter_rd_miso (latency: 2) - -- . : bin_arbiter_wr_mosi (latency: 4) - ----------------------------------------------------------------------------- - nxt_bin_arbiter_wr_mosi <= bin_writer_mosi; - -- Read RAM when subsequent addresses are not the same, when there is no toggle detected and only when the same address is not going to be written to. When a sync is detected don't read in the old RAM block. - nxt_bin_arbiter_rd_mosi.rd <= bin_reader_mosi.rd WHEN (bin_reader_mosi.address /= prev_bin_reader_mosi.address AND bin_reader_mosi.address /= bin_reader_mosi_pp.address - AND NOT(bin_reader_mosi.address = bin_reader_mosi_ppp.address) AND sync_detect='0') - OR (init_phase = '1') ELSE '0'; - nxt_bin_arbiter_rd_mosi.address <= bin_reader_mosi.address; - - p_bin_arbiter_mosi : PROCESS(dp_clk, dp_rst) IS --, nxt_bin_arbiter_wr_mosi, nxt_bin_arbiter_rd_mosi + ------------------------------------------------------------------------------- + -- bin_arbiter : Take care of simultaneous rd/wr to the same RAM address + -- . Input: bin_reader_mosi (wants to read bins) + -- bin_writer_mosi (wants to write to bins) + -- bin_arbiter_rd_miso (carries the bins requested by bin_reader) + -- . Output: bin_arbiter_wr_mosi (wr requests to RAM) + -- bin_arbiter_rd_mosi (rd requests to RAM) + -- bin_reader_miso (carries the bins requested by bin_reader) + ------------------------------------------------------------------------------- + -- Really simple arbitration: always allow reads, only allow writes when possible (rd_addr != wr_addr). + write_allowed <= TRUE WHEN bin_writer_mosi.address/=bin_reader_mosi.address ELSE FALSE; + + bin_arbiter_rd_mosi.wr <= '0'; + bin_arbiter_rd_mosi.rd <= bin_reader_mosi.rd; -- Reading is always allowed + bin_arbiter_rd_mosi.address <= bin_reader_mosi.address; + + nxt_bin_arbiter_wr_mosi.rd <= '0'; + nxt_bin_arbiter_wr_mosi.wr <= bin_writer_mosi.wr WHEN write_allowed ELSE '0'; + nxt_bin_arbiter_wr_mosi.wrdata <= bin_writer_mosi.wrdata WHEN write_allowed ELSE (OTHERS=>'0'); + nxt_bin_arbiter_wr_mosi.address <= bin_writer_mosi.address WHEN write_allowed ELSE bin_reader_mosi.address; + + -- Forward the rd_miso to the bin_reader + bin_reader_miso <= bin_arbiter_rd_miso; + + -- Register the outputs to RAM + p_bin_arbiter_mosi : PROCESS(dp_clk, dp_rst) IS BEGIN IF dp_rst = '1' THEN bin_arbiter_wr_mosi <= c_mem_mosi_rst; - bin_arbiter_rd_mosi <= c_mem_mosi_rst; ELSIF RISING_EDGE(dp_clk) THEN bin_arbiter_wr_mosi <= nxt_bin_arbiter_wr_mosi; - bin_arbiter_rd_mosi <= nxt_bin_arbiter_rd_mosi; END IF; END PROCESS; - --- -- Temporary debug data --- sla_out_ram_miso.rddata <= bin_arbiter_wr_mosi.wrdata; - - -- Make RAM data available for the bin_reader (or bin_writer) - bin_arbiter_rd_miso <= common_ram_r_w_miso; - - - ----------------------------------------------------------------------------- - -- RAM selector & Dual swapped RAM instances: - -- 4 cycles after a sync the RAM block is swapped for an empty one to allow - -- the block to be read out till the next sync+3 cycles - -- The input is the st side, the output is the dp clocked mm side. - -- - -- Depending on ram_pointer: - -- ram_pointer = '0': input RAM_0, output RAM_1 - -- ram_pointer = '1': input RAM_1, output RAM_0 - -- - -- input in: snk_in_pppp.sync (latency: 4) - -- bin_arbiter_wr_mosi (latency: 4) - -- bin_arbiter_rd_mosi (latency: 1) - -- out: common_ram_r_w_miso (latency: 2) - -- - -- output in: ram_out_wr_en; ram_out_wr_dat; ram_out_wr_adr; ram_out_rd_adr; - -- ram_out_rd_en - -- out: ram_out_rd_dat; ram_out_rd_val - ----------------------------------------------------------------------------- - p_ram_pointer_at_sync : PROCESS(snk_in_pppp) IS -- needs nxt_ram_pointer ?? - BEGIN - IF snk_in_pppp.sync = '1' THEN --needs snk_in_pppp <-- - ram_pointer <= NOT(ram_pointer); - END IF; - END PROCESS; - - p_ram_pointer : PROCESS(ram_pointer, bin_arbiter_wr_mosi, bin_arbiter_rd_mosi, ram_0_rd_dat, ram_0_rd_val, - ram_out_wr_en, ram_out_wr_dat, ram_out_wr_adr, ram_out_rd_adr, ram_out_rd_en, ram_1_rd_dat, ram_1_rd_val) IS - BEGIN - IF ram_pointer='0' THEN - - -- ST side (RAM 0) - ram_0_wr_en <= bin_arbiter_wr_mosi.wr; -- bin_arbiter_wr_mosi.wr wr_en - ram_0_wr_dat <= bin_arbiter_wr_mosi.wrdata(c_word_w-1 DOWNTO 0); -- bin_arbiter_wr_mosi.wrdata wr_dat - ram_0_wr_adr <= bin_arbiter_wr_mosi.address(c_adr_w-1 DOWNTO 0); -- bin_arbiter_wr_mosi.address wr_adr - ram_0_rd_adr <= bin_arbiter_rd_mosi.address(c_adr_w-1 DOWNTO 0); -- bin_arbiter_rd_mosi.address rd_adr - ram_0_rd_en <= bin_arbiter_rd_mosi.rd; -- bin_arbiter_rd_mosi.rd rd_en - common_ram_r_w_miso.rddata(c_word_w-1 DOWNTO 0) <= ram_0_rd_dat; -- common_ram_r_w_miso.rddata rd_dat - common_ram_r_w_miso.rdval <= ram_0_rd_val; -- common_ram_r_w_miso.rdval rd_val - - - -- dp_clk'd MM side (RAM 1) - ram_1_wr_en <= ram_out_wr_en; - ram_1_wr_dat <= ram_out_wr_dat; - ram_1_wr_adr <= ram_out_wr_adr; - ram_1_rd_adr <= ram_out_rd_adr; - ram_1_rd_en <= ram_out_rd_en; - ram_out_rd_dat <= ram_1_rd_dat; - ram_out_rd_val <= ram_1_rd_val; - - - ELSE -- ram_pointer='1' - - -- ST side (RAM 1) - ram_1_wr_en <= bin_arbiter_wr_mosi.wr; - ram_1_wr_dat <= bin_arbiter_wr_mosi.wrdata(c_word_w-1 DOWNTO 0); - ram_1_wr_adr <= bin_arbiter_wr_mosi.address(c_adr_w-1 DOWNTO 0); - ram_1_rd_adr <= bin_arbiter_rd_mosi.address(c_adr_w-1 DOWNTO 0); - ram_1_rd_en <= bin_arbiter_rd_mosi.rd; - common_ram_r_w_miso.rddata(c_word_w-1 DOWNTO 0) <= ram_1_rd_dat; - common_ram_r_w_miso.rdval <= ram_1_rd_val; - - --dp_clk'd MM side (RAM 0) - ram_0_wr_en <= ram_out_wr_en; - ram_0_wr_dat <= ram_out_wr_dat; - ram_0_wr_adr <= ram_out_wr_adr; - ram_0_rd_adr <= ram_out_rd_adr; - ram_0_rd_en <= ram_out_rd_en; - ram_out_rd_dat <= ram_0_rd_dat; - ram_out_rd_val <= ram_0_rd_val; - END IF; - END PROCESS; - - - -- Dual swapped RAM instances - ram_0: ENTITY common_lib.common_ram_r_w - GENERIC MAP ( - g_technology => c_tech_select_default, - g_ram => c_ram, - g_init_file => "UNUSED" - ) - PORT MAP ( - rst => dp_rst, - clk => dp_clk, - clken => '1', -- only necessary for Stratix iv - wr_en => ram_0_wr_en, - wr_adr => ram_0_wr_adr, - wr_dat => ram_0_wr_dat, - rd_en => ram_0_rd_en, - rd_adr => ram_0_rd_adr, - rd_dat => ram_0_rd_dat, - rd_val => ram_0_rd_val - ); - - ram_1: ENTITY common_lib.common_ram_r_w - GENERIC MAP ( - g_technology => c_tech_select_default, - g_ram => c_ram, - g_init_file => "UNUSED" - ) - PORT MAP ( - rst => dp_rst, - clk => dp_clk, - clken => '1', -- only necessary for Stratix iv - wr_en => ram_1_wr_en, - wr_adr => ram_1_wr_adr, - wr_dat => ram_1_wr_dat, - rd_en => ram_1_rd_en, - rd_adr => ram_1_rd_adr, - rd_dat => ram_1_rd_dat, - rd_val => ram_1_rd_val - ); - - - - ----------------------------------------------------------------------------- - -- Connect interface to DUAL swapped RAM, read out histogram statistics: - -- . Limit the data read by the MM master to the RAM block where it started - -- to read (the values read after a new sync will be OTHERS => '0') - -- . In the last g_nof_bins cycles all addresses will sequentially be cleared - -- - -- RAM selector: - -- input: ram_out_rd_dat; ram_out_rd_val - -- output: ram_out_wr_en; ram_out_wr_dat; ram_out_wr_adr; ram_out_rd_adr; - -- ram_out_wr_en - -- (PORT): - -- input: snk_in; sla_in_ram_mosi - -- output: sla_out_ram_miso - ----------------------------------------------------------------------------- - - -- Pipeline for identified illegal read requests after new sync - u_common_pipeline_sl_mm_adr_illegal : ENTITY common_lib.common_pipeline_sl - GENERIC MAP( - g_pipeline => 2 -- 0 for wires, > 0 for registers, - ) - PORT MAP ( - clk => dp_clk, - in_dat => mm_adr_illegal, - out_dat => mm_adr_illegal_pp - ); - - p_mm_adr_illegal : PROCESS(snk_in.sync, mm_adr_cnt) IS - BEGIN - IF snk_in.sync = '1' AND mm_adr_cnt /= 0 THEN - mm_adr_illegal <= '1'; - ELSIF mm_adr_cnt = g_nof_bins-1 THEN - mm_adr_illegal <= '0'; - ELSE - END IF; - END PROCESS; - - mm_adr_cnt <= TO_UINT(sla_in_ram_mosi.address(c_ram.adr_w-1 DOWNTO 0)) WHEN sla_in_ram_mosi.rd = '1'; - ram_out_same_w_r_adr <= '1' WHEN ram_out_wr_adr = sla_in_ram_mosi.address(c_ram.adr_w-1 DOWNTO 0) ELSE '0'; - - p_ram_to_fifo : PROCESS(snk_in_pp.sync, cycle_cnt, sla_in_ram_mosi.address, sla_in_ram_mosi.rd, ram_out_rd_dat, ram_out_rd_val, prev_ram_out_wr_adr, mm_adr_illegal_pp, ram_out_same_w_r_adr, bin_arbiter_wr_mosi.wrdata) IS - BEGIN - IF g_ram_miso_sim_mode = FALSE THEN - IF snk_in_pppp.sync = '1' THEN - ram_out_wr_en <= '0'; - nxt_cycle_cnt <= 0; - ELSIF cycle_cnt = c_clear THEN - ram_out_wr_adr <= (OTHERS => '0'); - ram_out_wr_dat <= (OTHERS => '0'); - ram_out_wr_en <= '1'; - IF ram_out_same_w_r_adr = '1' THEN - ram_out_rd_en <= '0'; - sla_out_ram_miso.rddata(c_ram.dat_w-1 DOWNTO 0) <= (OTHERS => '0'); - sla_out_ram_miso.rdval <= ram_out_rd_val; - ELSE - ram_out_rd_adr <= sla_in_ram_mosi.address(c_ram.adr_w-1 DOWNTO 0); - ram_out_rd_en <= sla_in_ram_mosi.rd; - sla_out_ram_miso.rddata(c_ram.dat_w-1 DOWNTO 0) <= ram_out_rd_dat; - sla_out_ram_miso.rdval <= ram_out_rd_val; - END IF; - nxt_cycle_cnt <= cycle_cnt +1; - ELSIF cycle_cnt > c_clear THEN - ram_out_wr_adr <= INCR_UVEC(prev_ram_out_wr_adr, 1); - ram_out_wr_dat <= (OTHERS => '0'); - nxt_cycle_cnt <= cycle_cnt +1; - IF ram_out_same_w_r_adr = '1' OR snk_in.sync = '1' THEN - sla_out_ram_miso.rddata(c_ram.dat_w-1 DOWNTO 0) <= (OTHERS => '0'); - sla_out_ram_miso.rdval <= ram_out_rd_val; - ELSE - ram_out_rd_adr <= sla_in_ram_mosi.address(c_ram.adr_w-1 DOWNTO 0); - ram_out_rd_en <= sla_in_ram_mosi.rd; - sla_out_ram_miso.rddata(c_ram.dat_w-1 DOWNTO 0) <= ram_out_rd_dat; - sla_out_ram_miso.rdval <= ram_out_rd_val; - END IF; - ram_out_wr_en <= '1'; - ELSIF mm_adr_illegal_pp = '1' THEN - ram_out_rd_adr <= sla_in_ram_mosi.address(c_ram.adr_w-1 DOWNTO 0); - ram_out_rd_en <= sla_in_ram_mosi.rd; - sla_out_ram_miso.rddata(c_ram.dat_w-1 DOWNTO 0) <= (OTHERS => '0'); - sla_out_ram_miso.rdval <= ram_out_rd_val; - nxt_cycle_cnt <= cycle_cnt +1; - ram_out_wr_en <= '0'; - ELSE - ram_out_rd_adr <= sla_in_ram_mosi.address(c_ram.adr_w-1 DOWNTO 0); - ram_out_rd_en <= sla_in_ram_mosi.rd; - sla_out_ram_miso.rddata(c_ram.dat_w-1 DOWNTO 0) <= ram_out_rd_dat; - sla_out_ram_miso.rdval <= ram_out_rd_val; - nxt_cycle_cnt <= cycle_cnt +1; - ram_out_wr_en <= '0'; - END IF; - dbg_ram_miso.rddata <= bin_arbiter_wr_mosi.wrdata; - ELSE - sla_out_ram_miso.rddata <= bin_arbiter_wr_mosi.wrdata; - END IF; - END PROCESS; - - - p_clk : PROCESS(dp_clk, dp_rst) - BEGIN - IF dp_rst='1' THEN - cycle_cnt <= 0; - ELSIF rising_edge(dp_clk) THEN - cycle_cnt <= nxt_cycle_cnt; - prev_ram_out_wr_adr <= ram_out_wr_adr; - END IF; - END PROCESS; - + + ------------------------------------------------------------------------------- + -- Two RAM (common_ram_r_w) instances. The user can read the histogram from the + -- instance that is not being written to by the bin_arbiter. + -- . Input: bin_arbiter_wr_mosi (writes bins) + -- bin_arbiter_rd_mosi (requests to read bins to increment bin count) + -- histogram_rd_mosi (requests to read the bins on the user side) + -- histogram_wr_mosi (on user side, auto clears RAM every sync) + -- . Output: histogram_rd_miso (carries the bins the user wants to read) + -- bin_arbiter_miso (carries then bins the bin_reader wants to read) + ------------------------------------------------------------------------------- + ram_pointer <= '0'; --FIXME This needs to be somehow tied to snk_in.sync. + + -- Let bin_arbiter write RAM 0 while user reads RAM 1 and vice versa + common_ram_r_w_wr_mosi_arr(0) <= bin_arbiter_wr_mosi WHEN ram_pointer='0' ELSE histogram_wr_mosi; + common_ram_r_w_rd_mosi_arr(0) <= bin_arbiter_rd_mosi WHEN ram_pointer='0' ELSE histogram_rd_mosi; + common_ram_r_w_wr_mosi_arr(1) <= bin_arbiter_wr_mosi WHEN ram_pointer='1' ELSE histogram_wr_mosi; + common_ram_r_w_rd_mosi_arr(1) <= bin_arbiter_rd_mosi WHEN ram_pointer='1' ELSE histogram_rd_mosi; + + -- Let bin_arbiter read RAM 0 while user reads RAM 1 and vice versa + bin_arbiter_rd_miso <= common_ram_r_w_rd_miso_arr(0) WHEN ram_pointer='0' ELSE common_ram_r_w_rd_miso_arr(1); + histogram_rd_miso <= common_ram_r_w_rd_miso_arr(1) WHEN ram_pointer='0' ELSE common_ram_r_w_rd_miso_arr(0); + + gen_common_ram_r_w : FOR i IN 0 TO c_nof_common_ram_r_w-1 GENERATE + u_common_ram_r_w : ENTITY common_lib.common_ram_r_w + GENERIC MAP ( + g_technology => c_tech_select_default, + g_ram => c_ram, + g_init_file => "UNUSED" + ) + PORT MAP ( + rst => dp_rst, + clk => dp_clk, + clken => '1', + wr_en => common_ram_r_w_wr_mosi_arr(i).wr, + wr_adr => common_ram_r_w_wr_mosi_arr(i).address(8-1 DOWNTO 0), + wr_dat => common_ram_r_w_wr_mosi_arr(i).wrdata(32-1 DOWNTO 0), + rd_en => common_ram_r_w_rd_mosi_arr(i).rd, + rd_adr => common_ram_r_w_rd_mosi_arr(i).address(8-1 DOWNTO 0), + rd_dat => common_ram_r_w_rd_miso_arr(i).rddata(32-1 DOWNTO 0), + rd_val => common_ram_r_w_rd_miso_arr(i).rdval + ); + END GENERATE; + + histogram_wr_mosi <= c_mem_mosi_rst; --FIXME add code to clear all RAM addresses here ? + + + ------------------------------------------------------------------------------- + -- Cross clock domains + -- . Input: histogram_rd_miso (from RAM block) + -- mm_histogram_rd_mosi (from user) + -- . Output: mm_histogram_rd_miso (towards user) + -- histogram_rd_mosi (towards RAM block) + ------------------------------------------------------------------------------- + -- FIXME We should do this in the MMS wrapper. END rtl; diff --git a/libraries/dsp/st/tb/vhdl/tb_st_histogram.vhd b/libraries/dsp/st/tb/vhdl/tb_st_histogram.vhd index faad666ee4..06f9e1d117 100644 --- a/libraries/dsp/st/tb/vhdl/tb_st_histogram.vhd +++ b/libraries/dsp/st/tb/vhdl/tb_st_histogram.vhd @@ -63,8 +63,8 @@ ENTITY tb_st_histogram IS GENERIC( g_sync_length : NATURAL := 200; g_nof_sync : NATURAL := 3; - g_data_w : NATURAL := 4; --4 ; 1 - g_nof_bins : NATURAL := 8; --8 ; 2 + g_data_w : NATURAL := 8; --4 ; 1 + g_nof_bins : NATURAL := 256; --8 ; 2 g_nof_data : NATURAL := 200; --g_str : STRING := "freq.density"; g_valid_gap : STRING := "custom"; -- "false" or "true" or "custom" --BOOLEAN := TRUE @@ -397,12 +397,12 @@ BEGIN dp_clk => dp_clk, -- Streaming - snk_in => st_histogram_snk_in, + snk_in => st_histogram_snk_in -- Memory Mapped - sla_in_ram_mosi => c_mem_mosi_rst,-- sla_in_ - sla_out_ram_miso => st_histogram_ram_miso, --OPEN -- sla_out_ - dbg_ram_miso => st_histogram_dbg_ram_miso +-- sla_in_ram_mosi => c_mem_mosi_rst,-- sla_in_ +-- sla_out_ram_miso => st_histogram_ram_miso, --OPEN -- sla_out_ +-- dbg_ram_miso => st_histogram_dbg_ram_miso ); -- GitLab