diff --git a/libraries/dsp/st/src/vhdl/mmp_st_histogram.vhd b/libraries/dsp/st/src/vhdl/mmp_st_histogram.vhd index f3b8d63dd9d07e43421c52ac82a05f86ba464ec4..98208bb34fca6202340cfc3ba3a3a26ec1b7e601 100644 --- a/libraries/dsp/st/src/vhdl/mmp_st_histogram.vhd +++ b/libraries/dsp/st/src/vhdl/mmp_st_histogram.vhd @@ -77,9 +77,7 @@ ARCHITECTURE str OF mmp_st_histogram IS CONSTANT c_addr_high : NATURAL := g_nof_bins-1; - SIGNAL common_ram_cr_cw_wr_copi_arr : t_mem_copi_arr(g_nof_instances-1 DOWNTO 0); - SIGNAL common_ram_cr_cw_rd_copi_arr : t_mem_copi_arr(g_nof_instances-1 DOWNTO 0); - SIGNAL common_ram_cr_cw_rd_cipo_arr : t_mem_cipo_arr(g_nof_instances-1 DOWNTO 0); + SIGNAL wr_copi_arr : t_mem_copi_arr(g_nof_instances-1 DOWNTO 0); ------------------------------------------------------------------------------- -- Logic to move st_histogram RAM contents into the dual clock RAM @@ -90,8 +88,8 @@ ARCHITECTURE str OF mmp_st_histogram IS SIGNAL ram_fill : STD_LOGIC; SIGNAL ram_filling : STD_LOGIC; SIGNAL nxt_ram_filling : STD_LOGIC; - SIGNAL address : STD_LOGIC_VECTOR(c_ram_adr_w-1 DOWNTO 0); - SIGNAL nxt_address : STD_LOGIC_VECTOR(c_ram_adr_w-1 DOWNTO 0); + SIGNAL ram_address : STD_LOGIC_VECTOR(c_ram_adr_w-1 DOWNTO 0); + SIGNAL nxt_ram_address : STD_LOGIC_VECTOR(c_ram_adr_w-1 DOWNTO 0); ------------------------------------------------------------------------------- -- MM multiplexing @@ -139,23 +137,19 @@ BEGIN wr_clk => dp_clk, wr_rst => dp_rst, wr_clken => '1', - wr_en => common_ram_cr_cw_wr_copi_arr(i).wr, - wr_adr => common_ram_cr_cw_wr_copi_arr(i).address(c_ram_adr_w-1 DOWNTO 0), - wr_dat => common_ram_cr_cw_wr_copi_arr(i).wrdata(c_ram_dat_w-1 DOWNTO 0), + wr_en => wr_copi_arr(i).wr, + wr_adr => wr_copi_arr(i).address(c_ram_adr_w-1 DOWNTO 0), + wr_dat => wr_copi_arr(i).wrdata(c_ram_dat_w-1 DOWNTO 0), rd_clk => mm_clk, rd_rst => mm_rst, rd_clken => '1', - rd_en => common_ram_cr_cw_rd_copi_arr(i).rd, - rd_adr => common_ram_cr_cw_rd_copi_arr(i).address(c_ram_adr_w-1 DOWNTO 0), - rd_dat => common_ram_cr_cw_rd_cipo_arr(i).rddata(c_ram_dat_w-1 DOWNTO 0), - rd_val => common_ram_cr_cw_rd_cipo_arr(i).rdval + rd_en => ram_copi_arr(i).rd, + rd_adr => ram_copi_arr(i).address(c_ram_adr_w-1 DOWNTO 0), + rd_dat => ram_cipo_arr(i).rddata(c_ram_dat_w-1 DOWNTO 0), + rd_val => ram_cipo_arr(i).rdval ); END GENERATE; - -- User side MM bus for histogram readout - common_ram_cr_cw_rd_copi_arr <= ram_copi_arr; - ram_cipo_arr <= common_ram_cr_cw_rd_cipo_arr; - ------------------------------------------------------------------------------- -- Logic to move st_histogram RAM contents into the dual clock RAM above @@ -163,33 +157,33 @@ BEGIN -- Use only the status signal of st_histogram instance 0 ram_fill <= snk_in_arr(0).sync; - -- Keep track of ram_filling status and address - nxt_ram_filling <= '0' WHEN TO_UINT(address)=c_addr_high ELSE '1' WHEN ram_fill='1' ELSE ram_filling; - nxt_address <= (OTHERS=>'0') WHEN ram_filling='0' ELSE INCR_UVEC(address, 1) WHEN ram_filling='1' ELSE address; + -- Keep track of ram_filling status and ram_address (used for reading and writing) + nxt_ram_filling <= '0' WHEN TO_UINT(ram_address)=c_addr_high ELSE '1' WHEN ram_fill='1' ELSE ram_filling; + nxt_ram_address <= (OTHERS=>'0') WHEN ram_filling='0' ELSE INCR_UVEC(ram_address, 1) WHEN ram_filling='1' ELSE ram_address; -- Do read request on ram_copi when ram_filling gen_copi_arr: FOR i IN 0 TO g_nof_instances-1 GENERATE st_histogram_ram_copi_arr(i).wr <= '0'; st_histogram_ram_copi_arr(i).wrdata <= (OTHERS=>'0'); st_histogram_ram_copi_arr(i).rd <= ram_filling; - st_histogram_ram_copi_arr(i).address(c_ram_adr_w-1 DOWNTO 0) <= address; + st_histogram_ram_copi_arr(i).address(c_ram_adr_w-1 DOWNTO 0) <= ram_address; END GENERATE; -- Forward the read histogram data from ram_cipo into write copi of dual clock RAM gen_rd_cipo_to_wr_copi: FOR i IN 0 TO g_nof_instances-1 GENERATE - common_ram_cr_cw_wr_copi_arr(i).wr <= st_histogram_ram_cipo_arr(i).rdval; - common_ram_cr_cw_wr_copi_arr(i).wrdata(c_ram_dat_w-1 DOWNTO 0) <= st_histogram_ram_cipo_arr(i).rddata(c_ram_dat_w-1 DOWNTO 0); - common_ram_cr_cw_wr_copi_arr(i).address(c_ram_adr_w-1 DOWNTO 0) <= address; + wr_copi_arr(i).wr <= st_histogram_ram_cipo_arr(i).rdval; + wr_copi_arr(i).wrdata(c_ram_dat_w-1 DOWNTO 0) <= st_histogram_ram_cipo_arr(i).rddata(c_ram_dat_w-1 DOWNTO 0); + wr_copi_arr(i).address(c_ram_adr_w-1 DOWNTO 0) <= ram_address; END GENERATE; -- Registers p_clk : PROCESS(dp_clk, dp_rst) IS BEGIN IF dp_rst = '1' THEN - address <= (OTHERS=>'0'); + ram_address <= (OTHERS=>'0'); ram_filling <= '0'; ELSIF RISING_EDGE(dp_clk) THEN - address <= nxt_address; + ram_address <= nxt_ram_address; ram_filling <= nxt_ram_filling; END IF; END PROCESS; diff --git a/libraries/dsp/st/src/vhdl/st_histogram.vhd b/libraries/dsp/st/src/vhdl/st_histogram.vhd index 5bc18db0f52cc561810ef66653252aba3fdda085..7be95283cb06c4a3dfec6f8ec8ab451a4061b2cc 100644 --- a/libraries/dsp/st/src/vhdl/st_histogram.vhd +++ b/libraries/dsp/st/src/vhdl/st_histogram.vhd @@ -24,9 +24,9 @@ -- . Count incoming data values and keep the counts in RAM as a histogram -- Description: -- . See st_histogram.txt for the original design description. --- . The histogram of all input data per sync (g_nof_data_per_sync) is --- kept as count values in g_nof_bins RAM addresses. g_nof_data_per_sync --- determines the required width of the data in RAM. +-- . The histogram of all input data per sync interval (g_nof_data_per_sync) +-- is kept as count values in g_nof_bins RAM addresses. +-- g_nof_data_per_sync determines the required width of the data in RAM. -- . All valid data of the input contributes to the histogram, no data is -- lost. This applies to any input type including DC. -- . Internally 2 RAM pages are used and are swapped on a sync. One @@ -35,8 +35,6 @@ -- of the inactive RAM are cleared automatically just before the next sync -- interval. This way no data is lost and all valid g_nof_data_per_sync -- samples contribute to the histogram. --- . tb_st_histogram generates and visualizes an input sine wave and the --- resulting histogram in the wave window. -- . The block schematic below shows the data flow from snk_in to ram_mosi: -- . snk_in.data is reduced by combining up to 3 consecutive identical -- samples into 1 and carrying the count (1..3) in the channel field. @@ -122,7 +120,7 @@ END st_histogram; ARCHITECTURE rtl OF st_histogram IS ------------------------------------------------------------------------------- - -- Constants derived from generics + -- Main Constants ------------------------------------------------------------------------------- CONSTANT c_ram_adr_w : NATURAL := ceil_log2(g_nof_bins); CONSTANT c_adr_low : NATURAL := g_data_w-c_ram_adr_w; @@ -136,8 +134,11 @@ ARCHITECTURE rtl OF st_histogram IS ------------------------------------------------------------------------------- -- snk_in_reg_arr ------------------------------------------------------------------------------- - SIGNAL snk_in_reg_arr : t_dp_sosi_arr(3 DOWNTO 0); - SIGNAL nxt_snk_in_reg_arr : t_dp_sosi_arr(3 DOWNTO 0); + CONSTANT c_ram_rd_wr_latency : NATURAL := 3; -- RAM read,incr,write cycle latency + CONSTANT c_shiftreg_depth : NATURAL := c_ram_rd_wr_latency+1; + + SIGNAL snk_in_reg_arr : t_dp_sosi_arr(c_shiftreg_depth DOWNTO 0); + SIGNAL nxt_snk_in_reg_arr : t_dp_sosi_arr(c_shiftreg_depth DOWNTO 0); SIGNAL snk_in_reg : t_dp_sosi; ------------------------------------------------------------------------------- @@ -222,8 +223,9 @@ BEGIN -- Slightly reduce the incoming data to prevent simultineous read/write -- . Take out every 2nd and 3rd duplicate data value (set valid='0') -- . Put the number of duplicates in the channel field to be applied downstream - -- . With a RAM read->write latency of 2 cycles, we need a shift register of 3 - -- words (0,1,2) deep to prevent simultaneous read/writes on the RAM. + -- . With a RAM read->write latency of 3 cycles, we need a shift register of 4 + -- words (0,1,2,3) deep to prevent simultaneous read/writes on the RAM. + -- . Element 3 is only and output register -- . A sequence of duplicate data could cross a sync period: -- . We need to stop&restart counting duplicates on a sync, don't count -- across sync periods @@ -239,7 +241,7 @@ BEGIN ------------------------------------------------------------------------------- p_nxt_snk_in_reg_arr: PROCESS(snk_in, snk_in_data, snk_in_reg_arr) IS BEGIN - FOR i IN 0 TO 3 LOOP + FOR i IN 0 TO c_shiftreg_depth-1 LOOP nxt_snk_in_reg_arr(i) <= c_dp_sosi_rst; END LOOP; @@ -297,7 +299,7 @@ BEGIN -- Registers p_snk_in_reg_arr: PROCESS(dp_clk, dp_rst) IS BEGIN - FOR i IN 0 TO 3 LOOP + FOR i IN 0 TO c_shiftreg_depth-1 LOOP IF dp_rst = '1' THEN snk_in_reg_arr(i) <= c_dp_sosi_rst; ELSIF RISING_EDGE(dp_clk) THEN diff --git a/libraries/dsp/st/tb/vhdl/tb_st_histogram.vhd b/libraries/dsp/st/tb/vhdl/tb_st_histogram.vhd index b4410b98bb0e7b94437fe353058676095a124b83..34f8314d4ff9542bda2c9dce40247e3edad7157c 100644 --- a/libraries/dsp/st/tb/vhdl/tb_st_histogram.vhd +++ b/libraries/dsp/st/tb/vhdl/tb_st_histogram.vhd @@ -32,6 +32,8 @@ -- . For signals 'stimuli_data' and 'histogram' select Format->Analog(automatic) -- . set Radix to 'decimal' for signed input data. -- Description: +-- . tb_st_histogram generates and visualizes an input sine wave and the +-- resulting histogram in the wave window. -- . Verification be eye (wave window): -- . For the sine input (default), observe input 'stimuli_data' and output -- 'histogram' signals. Set Radix->Decimal and Format->Analog (automatic)