diff --git a/libraries/dsp/st/src/vhdl/st_histogram.vhd b/libraries/dsp/st/src/vhdl/st_histogram.vhd index ae41451db0a3e9ea0a876956bad7e207efe52d63..effd491ef56cf3b37346761b95a8080886c282c4 100644 --- a/libraries/dsp/st/src/vhdl/st_histogram.vhd +++ b/libraries/dsp/st/src/vhdl/st_histogram.vhd @@ -20,7 +20,7 @@ -- Author: -- . Daniel van der Schuur --- . Jan Oudman (first version) +-- . Jan Oudman -- Purpose: -- . Count incoming data values and keep the counts in RAM as a histogram -- Description: @@ -64,6 +64,8 @@ ENTITY st_histogram IS snk_in : IN t_dp_sosi; + ram_clear : IN STD_LOGIC; + ram_mosi : IN t_mem_mosi; ram_miso : OUT t_mem_miso ); @@ -134,6 +136,15 @@ ARCHITECTURE rtl OF st_histogram IS SIGNAL histogram_rd_mosi : t_mem_mosi; SIGNAL histogram_rd_miso : t_mem_miso; + ------------------------------------------------------------------------------- + -- ram_clear + ------------------------------------------------------------------------------- + SIGNAL address : STD_LOGIC_VECTOR(c_adr_w-1 DOWNTO 0); + SIGNAL nxt_address : STD_LOGIC_VECTOR(c_adr_w-1 DOWNTO 0); + + SIGNAL ram_clearing : STD_LOGIC; + SIGNAL nxt_ram_clearing : STD_LOGIC; + BEGIN ------------------------------------------------------------------------------- @@ -280,10 +291,8 @@ BEGIN common_ram_r_w_rd_mosi_arr(1) <= bin_arbiter_rd_mosi WHEN bin_arbiter_rd_ram_pointer='1' ELSE histogram_rd_mosi; -- Let bin_arbiter read RAM 0 while user reads RAM 1 and vice versa - -- . We always want the MISO bus to switch 1 cycle later than the MOSI (such that the MM operation can finish). + -- . We always want the MISO bus to switch 1 cycle later than the MOSI (such that the MM operation can finish); hence using prv_bin_arbiter_rd_ram_pointer. bin_arbiter_rd_miso <= common_ram_r_w_rd_miso_arr(0) WHEN prv_bin_arbiter_rd_ram_pointer='0' ELSE common_ram_r_w_rd_miso_arr(1); - - -- histogram_rd_miso <= common_ram_r_w_rd_miso_arr(1) WHEN bin_arbiter_rd_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 @@ -307,8 +316,38 @@ BEGIN ); END GENERATE; - histogram_wr_mosi <= c_mem_mosi_rst; --FIXME add code to clear all RAM addresses here ? + ------------------------------------------------------------------------------- + -- ram_clear control input - let user clear the RAM + -- 1) User waits for PPS + -- 2) User reads data from RAM + -- . Logic here takes care that unused RAM is being read + -- 3) User sets ram_clear register + -- . Logic clears unused (at that exact time) RAM but does not compensate + -- for user being late (the ram pointer is checked only the very moment + -- ram_clear is set) + ------------------------------------------------------------------------------- + -- Signal to indicate when RAM is being cleared + nxt_ram_clearing <= '1' WHEN ram_clear='1' ELSE '0' WHEN TO_UINT(address)=c_nof_bins-1 ELSE ram_clearing; + + -- Address counter: 0 to g_nof_bins-1. + nxt_address <= INCR_UVEC(address, 1) WHEN ram_clearing='1' OR ram_clear='1' ELSE (OTHERS=>'0'); + histogram_wr_mosi.wr <= ram_clearing; + histogram_wr_mosi.address(c_adr_w-1 DOWNTO 0) <= address; + histogram_wr_mosi.wrdata <= (OTHERS=>'0'); + histogram_wr_mosi.rd <= '0'; + + -- Registers + p_ram_clearing : PROCESS(dp_clk, dp_rst) IS + BEGIN + IF dp_rst = '1' THEN + address <= (OTHERS=>'0'); + ram_clearing <= '0'; + ELSIF RISING_EDGE(dp_clk) THEN + address <= nxt_address; + ram_clearing <= nxt_ram_clearing; + END IF; + END PROCESS; ------------------------------------------------------------------------------- -- Cross clock domains diff --git a/libraries/dsp/st/tb/vhdl/tb_st_histogram.vhd b/libraries/dsp/st/tb/vhdl/tb_st_histogram.vhd index 0c7572b1d167c42278807db043ca9a7baf03ab22..e0ada8987a816a22f6f61ddf1a8b16334675291b 100644 --- a/libraries/dsp/st/tb/vhdl/tb_st_histogram.vhd +++ b/libraries/dsp/st/tb/vhdl/tb_st_histogram.vhd @@ -24,10 +24,18 @@ -- . Daniel van der Schuur -- . Jan Oudman -- Purpose: --- . +-- . Generate st_histogram input data and clear its RAM -- Description: --- . Generate data 0..99 twice per sync interval --- . Each value is counted twice per sync interval +-- . Verification be eye (wave window) - observe that: +-- . There are 4 sync periods in which 3 packets of 1024 words are generated; +-- . histogram_snk_in.data = 0..1023, 3 times per sync +-- . st_histogram has 256 bins so uses the 8 MS bits of snk_in.data +-- . st_histogram will count 4*0..255 instead of 0..1023 per packet +-- . st_histogram will count 12 occurences (3 packets * 4 * 0..255) per sync. +-- . bin_writer_mosi writes bin counts 1..12 per sync interval; +-- . Both RAMs are used twice: RAM 0, RAM 1, RAM 0, RAM 1; +-- . RAM clearing completes just before the end of each sync interval. +-- . ------------------------------------------------------------------------------- LIBRARY IEEE, common_lib, mm_lib, dp_lib; @@ -54,6 +62,17 @@ END tb_st_histogram; ARCHITECTURE tb OF tb_st_histogram IS + + --------------------------------------------------------------------------- + -- Sim parameters + -- . We're simulating at least 4 c_nof_sync_periods so both RAMs are written + -- and cleared twice. + --------------------------------------------------------------------------- + CONSTANT c_nof_sync_periods : NATURAL := 4; + CONSTANT c_nof_packets_per_sync : NATURAL := 3; + CONSTANT c_nof_data_per_packet : NATURAL := 4*g_nof_bins; + CONSTANT c_nof_data_per_sync : NATURAL := c_nof_packets_per_sync*c_nof_data_per_packet; + CONSTANT c_nof_data_before_ram_clear : NATURAL := c_nof_data_per_sync-g_nof_bins; -- Clear RAM just before next Sync interval --------------------------------------------------------------------------- -- Clocks and resets @@ -66,20 +85,19 @@ ARCHITECTURE tb OF tb_st_histogram IS SIGNAL tb_end : STD_LOGIC := '0'; ---------------------------------------------------------------------------- - -- Streaming Input + -- stimuli ---------------------------------------------------------------------------- SIGNAL stimuli_en : STD_LOGIC := '1'; SIGNAL stimuli_src_out : t_dp_sosi; SIGNAL stimuli_src_in : t_dp_siso; - SIGNAL st_histogram_snk_in : t_dp_sosi; - - ---------------------------------------------------------------------------- - -- Histogram readout + -- st_histogram ---------------------------------------------------------------------------- - SIGNAL st_histogram_ram_miso : t_mem_miso; + SIGNAL st_histogram_snk_in : t_dp_sosi; + SIGNAL st_histogram_ram_miso : t_mem_miso; + SIGNAL st_histogram_ram_clear : STD_LOGIC; BEGIN @@ -89,43 +107,52 @@ BEGIN ---------------------------------------------------------------------------- dp_clk <= NOT dp_clk OR tb_end AFTER c_dp_clk_period/2; dp_rst <= '1', '0' AFTER c_dp_clk_period*10; - + + ---------------------------------------------------------------------------- - -- Source: stimuli + -- Stimuli: generate st_histogram input data and clear the RAM ---------------------------------------------------------------------------- - p_stimuli_st : PROCESS + stimuli_src_in <= c_dp_siso_rdy; + + -- Generate c_nof_sync_periods*c_nof_packets_per_sync packets of c_nof_data_per_packet words + p_generate_packets : PROCESS VARIABLE v_sosi : t_dp_sosi := c_dp_sosi_rst; BEGIN - -- Adjust initial sosi field values by -1 to compensate for auto increment --- v_sosi.data := INCR_UVEC(TO_DP_DATA(0), -1); - stimuli_src_out <= c_dp_sosi_rst; proc_common_wait_until_low(dp_clk, dp_rst); proc_common_wait_some_cycles(dp_clk, 5); - -- Generate c_nof_repeat packets - FOR I IN 0 TO 10-1 LOOP - -- Auto increment v_sosi field values for this packet - v_sosi.sync := NOT(v_sosi.sync); --- v_sosi.data := INCR_UVEC(v_sosi.data, 1); - v_sosi.data := RESIZE_DP_DATA(v_sosi.data(g_data_w-1 DOWNTO 0)); -- wrap when >= 2**g_data_w - - -- Send packet - proc_dp_gen_block_data(g_data_w, TO_UINT(v_sosi.data), 100, TO_UINT(v_sosi.channel), TO_UINT(v_sosi.err), v_sosi.sync, v_sosi.bsn, dp_clk, stimuli_en, stimuli_src_in, stimuli_src_out); - - -- Insert optional gap between the packets --- proc_common_wait_some_cycles(clk, g_pkt_gap); - END LOOP; - - -- Signal end of stimuli + FOR I IN 0 TO c_nof_sync_periods-1 LOOP + v_sosi.sync := '1'; + FOR I IN 0 TO c_nof_packets_per_sync-1 LOOP + v_sosi.data := RESIZE_DP_DATA(v_sosi.data(g_data_w-1 DOWNTO 0)); -- wrap when >= 2**g_data_w + proc_dp_gen_block_data(g_data_w, TO_UINT(v_sosi.data), c_nof_data_per_packet, TO_UINT(v_sosi.channel), TO_UINT(v_sosi.err), v_sosi.sync, v_sosi.bsn, dp_clk, stimuli_en, stimuli_src_in, stimuli_src_out); + v_sosi.sync := '0'; + END LOOP; + END LOOP; + proc_common_wait_some_cycles(dp_clk, 50); tb_end <= '1'; WAIT; END PROCESS; - - stimuli_src_in <= c_dp_siso_rdy; - + -- Clear the RAM + p_ram_clear : PROCESS + BEGIN + FOR I IN 0 TO c_nof_sync_periods-1 LOOP + -- Sync up with p_generate_packets above by waiting for stimuli_src_out.sync + proc_common_wait_until_high(dp_clk, stimuli_src_out.sync); + -- Wait until c_nof_data_before_ram_clear cycles have passed + st_histogram_ram_clear <= '0'; + proc_common_wait_some_cycles(dp_clk, c_nof_data_before_ram_clear-1); + -- Toggle RAM clear for 1 cycle + st_histogram_ram_clear <= '1'; + proc_common_wait_some_cycles(dp_clk, 1); + st_histogram_ram_clear <= '0'; + END LOOP; + END PROCESS; + + ---------------------------------------------------------------------------- -- st_histogram ---------------------------------------------------------------------------- @@ -143,11 +170,11 @@ BEGIN dp_rst => dp_rst, snk_in => st_histogram_snk_in, + + ram_clear => st_histogram_ram_clear, ram_mosi => c_mem_mosi_rst, ram_miso => st_histogram_ram_miso - ); - END tb;