Skip to content
Snippets Groups Projects
Commit 14f4e1dc authored by Daniel van der Schuur's avatar Daniel van der Schuur
Browse files

Merge branch 'L2SDP-88' into 'master'

Resolve L2SDP-88

Closes L2SDP-88

See merge request desp/hdl!21
parents 1607e3e3 7f986b37
Branches
No related tags found
2 merge requests!43Master,!21Resolve L2SDP-88
...@@ -21,6 +21,7 @@ test_bench_files = ...@@ -21,6 +21,7 @@ test_bench_files =
tb/vhdl/tb_mmf_st_sst.vhd tb/vhdl/tb_mmf_st_sst.vhd
tb/vhdl/tb_st_histogram.vhd tb/vhdl/tb_st_histogram.vhd
tb/vhdl/tb_mms_st_histogram.vhd tb/vhdl/tb_mms_st_histogram.vhd
tb/vhdl/tb_tb_st_histogram.vhd
regression_test_vhdl = regression_test_vhdl =
tb/vhdl/tb_st_acc.vhd tb/vhdl/tb_st_acc.vhd
......
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
-- Description: -- Description:
-- The histogram component separates it's input samples in counter bins based -- 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 -- 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 -- 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 -- cycles. While one RAM block is used to count the input samples, the other
-- is read by the MM bus through st_histogram_reg. -- is read by the MM bus through st_histogram_reg.
-- --
...@@ -47,6 +47,14 @@ ...@@ -47,6 +47,14 @@
-- If the MM bus needs to acces the data in a RAM block it has to acces it -- 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. -- 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: -- Remarks:
-- . Because the values of the generics g_nof_bins depends on g_in_data_w -- . 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 -- (you should not have more bins than data values) an assert is made to
...@@ -54,9 +62,10 @@ ...@@ -54,9 +62,10 @@
-- If exceeded the simulator will throw fatal error ("...Port length (#) does -- If exceeded the simulator will throw fatal error ("...Port length (#) does
-- not match actual length (#)...") -- not match actual length (#)...")
-- --
-- . when an adress is determined it takes 1 cycle to receive it's value and -- . 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 -- 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 -- 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 -- on the same adress at the same time. These limitations cause the following
-- complications in the implementation: -- complications in the implementation:
-- . repeating samples of the same adress have to be counted first till -- . repeating samples of the same adress have to be counted first till
...@@ -64,9 +73,11 @@ ...@@ -64,9 +73,11 @@
-- further consecutive samples and have the read/write limitation) -- further consecutive samples and have the read/write limitation)
-- . If adresses are toggling at every cycle (e.g. adress 0; 1; 0; 1) you -- . 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 -- 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 -- read/write limitation (missing samples) and writing takes priority
-- . When a sync signal appears the RAM has to be swapped 2 cycles later so -- in this case
-- the first 2 cycles may not be read from the old RAM block -- . 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)
-- --
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
...@@ -82,7 +93,8 @@ ENTITY st_histogram IS ...@@ -82,7 +93,8 @@ ENTITY st_histogram IS
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_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_bins : NATURAL := 512; -- is a power of 2 and g_nof_bins <= c_data_span; max. 512
g_nof_data : NATURAL; -- g_nof_data : NATURAL; --
g_str : STRING := "freq.density" -- to select output to MM bus ("frequency" or "freq.density") 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 ( PORT (
dp_rst : IN STD_LOGIC; dp_rst : IN STD_LOGIC;
...@@ -93,53 +105,96 @@ ENTITY st_histogram IS ...@@ -93,53 +105,96 @@ ENTITY st_histogram IS
-- DP clocked memory bus -- DP clocked memory bus
sla_in_ram_mosi : IN t_mem_mosi; -- Beware, works in dp clock domain ! sla_in_ram_mosi : IN t_mem_mosi; -- Beware, works in dp clock domain !
sla_out_ram_miso : OUT t_mem_miso -- '' ! sla_out_ram_miso : OUT t_mem_miso; -- '' !
-- ram_mosi : IN t_mem_mosi; -- Beware, works in dp clock domain ! -- ram_mosi : IN t_mem_mosi; -- Beware, works in dp clock domain !
-- ram_miso : OUT t_mem_miso -- '' ! -- ram_miso : OUT t_mem_miso -- '' !
-- Debug bus
dbg_ram_miso : OUT t_mem_miso
); );
END st_histogram; END st_histogram;
ARCHITECTURE rtl OF st_histogram IS ARCHITECTURE rtl OF st_histogram IS
CONSTANT c_data_span : NATURAL := pow2(g_in_data_w); -- any use? -- 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_bin_w : NATURAL := ceil_log2(g_nof_data); -- any use?
CONSTANT c_clear : NATURAL := g_nof_data - g_nof_bins; CONSTANT c_clear : NATURAL := g_nof_data - g_nof_bins;
CONSTANT c_adr_w : NATURAL := ceil_log2(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_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_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, CONSTANT c_ram : t_c_mem := (latency => 1,
adr_w => c_adr_w, -- 9 bits needed to adress/select 512 adresses 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 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 nof_dat => g_nof_bins, -- 512 adresses with 32 bit words, so 512
init_sl => '0'); -- MM side : sla_in, sla_out init_sl => '0'); -- MM side : sla_in, sla_out
SIGNAL dp_pipeline_src_out_p : t_dp_sosi; -- CONSTANT c_mem_miso_setting : t_mem_miso := (rddata => mem_miso_init, -- c_mem_miso_rst; -- limit to 32 bit
SIGNAL dp_pipeline_src_out_pp : t_dp_sosi; -- 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;
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 rd_adr_cnt : NATURAL := 1; SIGNAL bin_arbiter_rd_miso : t_mem_miso := c_mem_miso_rst;
SIGNAL nxt_rd_adr_cnt : NATURAL; SIGNAL bin_reader_rd_miso : t_mem_miso := c_mem_miso_rst;
SIGNAL prev_rd_adr : STD_LOGIC_VECTOR(g_in_data_w -1 DOWNTO c_adr_low); SIGNAL common_ram_r_w_miso : t_mem_miso := c_mem_miso_rst;
-- Toggle implementation signals SIGNAL init_phase : STD_LOGIC := '1';
SIGNAL prev_same_r_w_adr : STD_LOGIC := '0'; SIGNAL nxt_init_phase : STD_LOGIC;
SIGNAL same_r_w_adr : STD_LOGIC := '0';
SIGNAL nxt_same_r_w_adr : STD_LOGIC := '0'; 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 ram_pointer : STD_LOGIC := '0';
SIGNAL cycle_cnt : NATURAL := 0 ; SIGNAL cycle_cnt : NATURAL := 0 ;
SIGNAL nxt_cycle_cnt : NATURAL := 0 ; SIGNAL nxt_cycle_cnt : NATURAL := 0 ;
SIGNAL wr_en : STD_LOGIC := '0'; -- SIGNAL wr_en : STD_LOGIC := '0';
SIGNAL nxt_wr_en : STD_LOGIC; -- SIGNAL nxt_wr_en : STD_LOGIC;
SIGNAL wr_dat : STD_LOGIC_VECTOR(c_word_w -1 DOWNTO 0); -- 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 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 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_adr : STD_LOGIC_VECTOR(g_in_data_w -1 DOWNTO c_adr_low);
SIGNAL rd_en : STD_LOGIC := '0'; -- SIGNAL rd_en : STD_LOGIC := '0';
SIGNAL rd_dat : STD_LOGIC_VECTOR(c_word_w -1 DOWNTO 0); -- SIGNAL rd_dat : STD_LOGIC_VECTOR(c_word_w -1 DOWNTO 0);
SIGNAL rd_val : STD_LOGIC; -- SIGNAL rd_val : STD_LOGIC;
SIGNAL mm_adr_cnt : NATURAL := 0 ; SIGNAL mm_adr_cnt : NATURAL := 0 ;
SIGNAL mm_adr_illegal : STD_LOGIC := '0'; SIGNAL mm_adr_illegal : STD_LOGIC := '0';
...@@ -147,9 +202,7 @@ ARCHITECTURE rtl OF st_histogram IS ...@@ -147,9 +202,7 @@ ARCHITECTURE rtl OF st_histogram IS
SIGNAL ram_0_wr_en : STD_LOGIC; SIGNAL ram_0_wr_en : STD_LOGIC;
-- SIGNAL ram_0_wr_en_b : STD_LOGIC := '0'; -- pointer=1, temp'0'
SIGNAL ram_0_wr_dat : STD_LOGIC_VECTOR(c_word_w -1 DOWNTO 0); SIGNAL ram_0_wr_dat : STD_LOGIC_VECTOR(c_word_w -1 DOWNTO 0);
-- SIGNAL ram_0_wr_dat_b : STD_LOGIC_VECTOR(c_word_w -1 DOWNTO 0) := (OTHERS =>'0'); -- pointer=1, temp'0'
SIGNAL ram_0_wr_adr : STD_LOGIC_VECTOR(g_in_data_w -1 DOWNTO c_adr_low); 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_adr : STD_LOGIC_VECTOR(g_in_data_w -1 DOWNTO c_adr_low);
SIGNAL ram_0_rd_en : STD_LOGIC; SIGNAL ram_0_rd_en : STD_LOGIC;
...@@ -183,30 +236,57 @@ BEGIN ...@@ -183,30 +236,57 @@ 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; 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: -- Assign inputs of RAM: <-- use parts of description for bin_writer
-- . Determine address based on input data -- . Determine address based on input data
-- . Compare adress with the two previous adresses and if: -- . 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 the last adress increase a counter
-- . it is the same as 2 cycles back but not the last copy the data to be -- . 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 -- written directly into a local counter instead of trying to read (ask)
-- back from RAM at the same clock cycle (which is impossible) -- 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 -- . it is not the same enable the nxt_wr_dat data to be written .
-- at the next cycle by making nxt_wr_en high -- at the next cycle by making nxt_wr_en high .
-- . Write the wr_dat data to the RAM -- . Write the wr_dat data to the RAM
-- . At the snk_in.sync pulse: -- . At the snk_in.sync pulse:
-- . let first 2 cycles start counting from 0 again -- . let first 3 cycles start counting from 0 again
-- . (plus 2 cycles) let counting depend on values in RAM (which should -- . (plus 3 cycles) let counting depend on values in RAM (which should
-- be 0) -- be 0)
-- . Restart or pause counting when a snk_in.valid = '0' appears: -- . Restart or pause counting when a snk_in.valid = '0' appears:
-- . pause when adress is the same as the previous adress -- . 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 adress is not the same as previous adress
-- . restart from 0 when also a sync appears -- . restart from 0 when also a sync appears
-- --
-- input: snk_in; rd_dat; rd_val --
-- output: wr_adr; rd_adr; wr_en; rd_en; wr_dat; -- . 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)
--
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
-- cycles after sync -----------------------------------------------------------------------------
-- 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 u_dp_pipeline_snk_in_1_cycle : ENTITY dp_lib.dp_pipeline
GENERIC MAP ( GENERIC MAP (
g_pipeline => 1 -- 0 for wires, > 0 for registers, g_pipeline => 1 -- 0 for wires, > 0 for registers,
...@@ -215,46 +295,96 @@ BEGIN ...@@ -215,46 +295,96 @@ BEGIN
rst => dp_rst, rst => dp_rst,
clk => dp_clk, clk => dp_clk,
snk_in => snk_in, snk_in => snk_in,
src_out => dp_pipeline_src_out_p src_out => snk_in_p
); );
p_bin_cnt_switch : PROCESS(snk_in) IS -- misses g_nof_bins ?? -- 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 BEGIN
rd_adr <= (OTHERS =>'0'); IF dp_rst = '1' THEN
IF g_nof_bins>1 THEN init_phase <= '1';
rd_adr <= snk_in.data(g_in_data_w-1 DOWNTO c_adr_low);-- WHEN snk_in.valid='1' ELSE (OTHERS =>'0'); -- AND dp_rst='0'; 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 IF;
END PROCESS; END PROCESS;
-- Pipelined to compare previous rd_adr against current -- Enable sync comparisons
u_common_pipeline_adr_cnt : ENTITY common_lib.common_pipeline --rename to u_common_pipeline_rd_adr 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 ( GENERIC MAP (
g_representation => "UNSIGNED", --orig. signed g_representation => "UNSIGNED", --orig. signed
g_pipeline => 1, g_pipeline => 1,
g_in_dat_w => c_adr_w, g_in_dat_w => c_adr_w, -- c_mem_address_w
g_out_dat_w => c_adr_w g_out_dat_w => c_adr_w
) )
PORT MAP ( PORT MAP (
clk => dp_clk, clk => dp_clk,
clken => '1', clken => bin_reader_mosi.rd, -- '1',
in_dat => STD_LOGIC_VECTOR(rd_adr), in_dat => STD_LOGIC_VECTOR(bin_reader_mosi.address(c_adr_w-1 DOWNTO 0)),
out_dat => prev_rd_adr out_dat => prev_bin_reader_mosi.address(c_adr_w-1 DOWNTO 0)
); );
p_nxt_wr_en : PROCESS(prev_rd_adr, rd_adr, snk_in.sync) IS -- misses g_nof_bins ?? -- Enable adress comparisons 2 cycles back
BEGIN u_common_pipeline_bin_reader_mosi_2_cycle : ENTITY common_lib.common_pipeline
nxt_wr_en <= '0'; GENERIC MAP (
IF rd_adr /= prev_rd_adr THEN g_representation => "UNSIGNED", --orig. signed
nxt_wr_en <= '1'; g_pipeline => 1,
ELSIF snk_in.sync = '1' AND g_nof_bins = 1 THEN g_in_dat_w => c_adr_w,
nxt_wr_en <= '1'; g_out_dat_w => c_adr_w
ELSIF snk_in.sync = '1' THEN )
nxt_wr_en <= '1'; PORT MAP (
END IF; clk => dp_clk,
END PROCESS; 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)
);
-- requested data on adress can be written back 2 cycles later -- Enable adress comparisons 3 cycles back
u_common_pipeline_adr : ENTITY common_lib.common_pipeline u_common_pipeline_bin_reader_mosi_3_cycle : ENTITY common_lib.common_pipeline
GENERIC MAP ( GENERIC MAP (
g_representation => "UNSIGNED", --orig. signed g_representation => "UNSIGNED", --orig. signed
g_pipeline => 2, g_pipeline => 2,
...@@ -263,149 +393,219 @@ BEGIN ...@@ -263,149 +393,219 @@ BEGIN
) )
PORT MAP ( PORT MAP (
clk => dp_clk, clk => dp_clk,
clken => '1', in_dat => STD_LOGIC_VECTOR(prev_bin_reader_mosi.address(c_adr_w-1 DOWNTO 0)),
in_dat => STD_LOGIC_VECTOR(rd_adr), out_dat => bin_reader_mosi_ppp.address(c_adr_w-1 DOWNTO 0)
out_dat => wr_adr
); );
p_rd_en : PROCESS(dp_pipeline_src_out_p.sync, snk_in.valid, wr_en, wr_adr, rd_adr, prev_rd_adr) IS
BEGIN
rd_en <= '1';
IF dp_pipeline_src_out_p.sync = '1' AND wr_en = '1' THEN --
rd_en <= '0';
ELSIF wr_adr = rd_adr AND wr_adr /= prev_rd_adr THEN -- toggle implementation
rd_en <= '0'; -- toggle implementation
ELSIF snk_in.valid = '0' AND wr_en = '1' THEN
rd_en <= '1';
END IF;
END PROCESS;
-- cycles after sync -- 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
u_dp_pipeline_snk_in_2_cycle : ENTITY dp_lib.dp_pipeline 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( GENERIC MAP(
g_pipeline => 2 -- 0 for wires, > 0 for registers, g_pipeline => 2 -- 0 for wires, > 0 for registers,
) )
PORT MAP ( PORT MAP (
rst => dp_rst,
clk => dp_clk, clk => dp_clk,
snk_in => snk_in, in_dat => rd_cnt_allowed,
src_out => dp_pipeline_src_out_pp out_dat => rd_cnt_allowed_pp
); );
p_prev_adr_cnt : PROCESS(wr_adr, rd_adr, prev_rd_adr, rd_adr_cnt, snk_in.sync, snk_in.valid, dp_pipeline_src_out_p.valid, dp_pipeline_src_out_p.sync) IS --change to p_nxt_rd_adr_cnt ;; misses wr_dat; -- 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)
BEGIN 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') )
nxt_rd_adr_cnt <= 1; ELSE '0';
IF rd_adr = prev_rd_adr AND snk_in.valid = '1' AND snk_in.sync = '0' THEN
nxt_rd_adr_cnt <= rd_adr_cnt + 1 ;
ELSIF snk_in.valid = '0' AND snk_in.sync = '1' THEN --address doesn't matter at unvalid and sync, removed: rd_adr = prev_rd_adr AND
nxt_rd_adr_cnt <= 0;
ELSIF rd_adr = prev_rd_adr AND snk_in.valid = '0' THEN
nxt_rd_adr_cnt <= rd_adr_cnt;
ELSIF rd_adr = prev_rd_adr AND snk_in.valid = '1' AND dp_pipeline_src_out_p.valid = '0' AND snk_in.sync = '1' THEN -- toggle implementation; do the adresses even matter?
nxt_rd_adr_cnt <= 1; -- toggle implementation
ELSIF rd_adr = prev_rd_adr AND snk_in.valid = '1' AND dp_pipeline_src_out_p.valid = '0' THEN -- toggle implementation
nxt_rd_adr_cnt <= rd_adr_cnt + 1; -- toggle implementation
ELSIF wr_adr = rd_adr AND snk_in.valid = '1' AND snk_in.sync = '1' THEN -- toggle implementation; do the adresses even matter?
nxt_rd_adr_cnt <= 1; -- toggle implementation
ELSIF wr_adr = rd_adr AND rd_adr /= prev_rd_adr AND snk_in.valid = '0' THEN -- toggle implementation: disable count; -2 cycles count + 0
nxt_rd_adr_cnt <= TO_UINT(wr_dat); -- toggle implementation
ELSIF wr_adr = rd_adr AND snk_in.valid = '1' AND dp_pipeline_src_out_p.sync = '0' THEN -- toggle implentation
nxt_rd_adr_cnt <= TO_UINT(wr_dat) + 1; -- toggle implentation
ELSIF wr_adr = rd_adr AND snk_in.valid = '0' THEN -- toggle implentation
nxt_rd_adr_cnt <= rd_adr_cnt; -- toggle implentation
ELSIF snk_in.valid = '0' AND rd_adr /= prev_rd_adr AND wr_adr /= rd_adr THEN
nxt_rd_adr_cnt <= 0;
END IF;
END PROCESS;
p_nxt_same_r_w_adr : PROCESS(wr_adr, rd_adr) IS -- toggle implentation ;; misses g_nof_bins ??
BEGIN
nxt_same_r_w_adr <= '0';
IF wr_adr = rd_adr AND g_nof_bins > 1 THEN
nxt_same_r_w_adr <= '1';
END IF;
END PROCESS;
-- Pipeline for toggle issue -- Line up to p_nxt_bin_writer_mosi process
u_common_pipeline_sl_same_r_w_adr : ENTITY common_lib.common_pipeline_sl u_common_pipeline_sl_toggle_detect : ENTITY common_lib.common_pipeline_sl
GENERIC MAP( GENERIC MAP(
g_pipeline => 1 -- 0 for wires, > 0 for registers, 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 ( PORT MAP (
clk => dp_clk, clk => dp_clk,
in_dat => same_r_w_adr, in_dat => same_r_w_address,
out_dat => prev_same_r_w_adr out_dat => same_r_w_address_pp
); );
p_nxt_wr_dat : PROCESS(rd_dat, rd_adr_cnt, rd_val, dp_pipeline_src_out_p.sync, dp_pipeline_src_out_pp.sync, wr_en) IS --misses: same_r_w_adr; c_word_w?; prev_same_r_w_adr;
-----------------------------------------------------------------------------
-- 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 BEGIN
nxt_wr_dat <= (OTHERS => '0'); IF dp_rst = '1' THEN
IF dp_pipeline_src_out_p.sync = '1' THEN prev_wrdata <= 0;
nxt_wr_dat <= TO_UVEC(rd_adr_cnt, c_word_w); prev_prev_wrdata <= 0;
ELSIF dp_pipeline_src_out_pp.sync = '1' THEN prev_prev_prev_wrdata <= 0;
nxt_wr_dat <= TO_UVEC(rd_adr_cnt, c_word_w); ELSIF nxt_bin_writer_mosi.wr='1' AND RISING_EDGE(dp_clk) THEN
ELSIF same_r_w_adr = '1' AND rd_val = '0' THEN -- toggle implementation: same adress forced rd_val to 0, counter instead of ram knows what to write prev_wrdata <= nxt_prev_wrdata;
nxt_wr_dat <= TO_UVEC(rd_adr_cnt, c_word_w); -- toggle implementation prev_prev_wrdata <= prev_wrdata;
ELSIF dp_pipeline_src_out_pp.valid = '0' AND prev_same_r_w_adr = '1' THEN -- toggle implementation: prevent 2* rd_dat prev_prev_prev_wrdata <= prev_prev_wrdata;
nxt_wr_dat <= TO_UVEC(rd_adr_cnt, c_word_w); -- toggle implementation
ELSIF rd_val = '1' THEN
nxt_wr_dat <= INCR_UVEC(rd_dat, rd_adr_cnt);
END IF; END IF;
END PROCESS; END PROCESS;
p_clk : PROCESS(dp_clk, dp_rst) p_bin_writer_mosi : PROCESS(dp_clk, dp_rst) IS --, nxt_bin_writer_mosi, nxt_prev_wrdata, prev_wrdata, prev_prev_wrdata
BEGIN BEGIN
IF dp_rst = '1' THEN IF dp_rst = '1' THEN
rd_adr_cnt <= 0; bin_writer_mosi <= c_mem_mosi_rst;
wr_en <= '0'; -- prev_wrdata <= 0;
ELSIF rising_edge(dp_clk) THEN -- prev_prev_wrdata <= 0;
rd_adr_cnt <= nxt_rd_adr_cnt; -- prev_prev_prev_wrdata <= 0;
wr_dat <= nxt_wr_dat; ELSIF RISING_EDGE(dp_clk) THEN
wr_en <= nxt_wr_en; bin_writer_mosi <= nxt_bin_writer_mosi;
same_r_w_adr <= nxt_same_r_w_adr; -- IF nxt_bin_writer_mosi.wr = '1' THEN
cycle_cnt <= nxt_cycle_cnt; -- ( ander functieblok ) -- prev_wrdata <= nxt_prev_wrdata;
prev_ram_out_wr_adr <= ram_out_wr_adr; -- '' -- prev_prev_wrdata<= prev_wrdata;
-- prev_prev_prev_wrdata <= prev_prev_wrdata;
-- END IF;
END IF; END IF;
END PROCESS; 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
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: -- RAM selector & Dual swapped RAM instances:
-- 2 cycles after a sync the RAM block is swapped for an empty one to allow -- 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+2 cycles -- 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: -- Depending on ram_pointer:
-- ram_pointer = '0': input RAM_0, output RAM_1 -- ram_pointer = '0': input RAM_0, output RAM_1
-- ram_pointer = '1': input RAM_1, output RAM_0 -- ram_pointer = '1': input RAM_1, output RAM_0
-- --
-- input in: dp_pipeline_src_out_pp.sync; wr_en; wr_dat; wr_adr; -- input in: snk_in_pppp.sync (latency: 4)
-- rd_adr; rd_en; -- bin_arbiter_wr_mosi (latency: 4)
-- out: rd_dat, rd_val -- 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; -- output in: ram_out_wr_en; ram_out_wr_dat; ram_out_wr_adr; ram_out_rd_adr;
-- ram_out_rd_en -- ram_out_rd_en
-- out: ram_out_rd_dat; ram_out_rd_val -- out: ram_out_rd_dat; ram_out_rd_val
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
p_ram_pointer_at_sync : PROCESS(dp_pipeline_src_out_pp) IS -- needs nxt_ram_pointer ?? p_ram_pointer_at_sync : PROCESS(snk_in_pppp) IS -- needs nxt_ram_pointer ??
BEGIN BEGIN
IF dp_pipeline_src_out_pp.sync = '1' THEN IF snk_in_pppp.sync = '1' THEN --needs snk_in_pppp <--
ram_pointer <= NOT(ram_pointer); ram_pointer <= NOT(ram_pointer);
END IF; END IF;
END PROCESS; END PROCESS;
p_ram_pointer : PROCESS(ram_pointer, wr_en, wr_dat, wr_adr, rd_adr, rd_en, ram_0_rd_dat, ram_0_rd_val, 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 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 BEGIN
IF ram_pointer='0' THEN IF ram_pointer='0' THEN
-- ST side (RAM 0) -- ST side (RAM 0)
ram_0_wr_en <= wr_en; ram_0_wr_en <= bin_arbiter_wr_mosi.wr; -- bin_arbiter_wr_mosi.wr wr_en
ram_0_wr_dat <= wr_dat; 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 <= wr_adr; 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 <= rd_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 <= rd_en; ram_0_rd_en <= bin_arbiter_rd_mosi.rd; -- bin_arbiter_rd_mosi.rd rd_en
rd_dat <= ram_0_rd_dat; common_ram_r_w_miso.rddata(c_word_w-1 DOWNTO 0) <= ram_0_rd_dat; -- common_ram_r_w_miso.rddata rd_dat
rd_val <= ram_0_rd_val; 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) -- dp_clk'd MM side (RAM 1)
...@@ -421,13 +621,13 @@ BEGIN ...@@ -421,13 +621,13 @@ BEGIN
ELSE -- ram_pointer='1' ELSE -- ram_pointer='1'
-- ST side (RAM 1) -- ST side (RAM 1)
ram_1_wr_en <= wr_en; ram_1_wr_en <= bin_arbiter_wr_mosi.wr;
ram_1_wr_dat <= wr_dat; ram_1_wr_dat <= bin_arbiter_wr_mosi.wrdata(c_word_w-1 DOWNTO 0);
ram_1_wr_adr <= wr_adr; ram_1_wr_adr <= bin_arbiter_wr_mosi.address(c_adr_w-1 DOWNTO 0);
ram_1_rd_adr <= rd_adr; ram_1_rd_adr <= bin_arbiter_rd_mosi.address(c_adr_w-1 DOWNTO 0);
ram_1_rd_en <= rd_en; ram_1_rd_en <= bin_arbiter_rd_mosi.rd;
rd_dat <= ram_1_rd_dat; common_ram_r_w_miso.rddata(c_word_w-1 DOWNTO 0) <= ram_1_rd_dat;
rd_val <= ram_1_rd_val; common_ram_r_w_miso.rdval <= ram_1_rd_val;
--dp_clk'd MM side (RAM 0) --dp_clk'd MM side (RAM 0)
ram_0_wr_en <= ram_out_wr_en; ram_0_wr_en <= ram_out_wr_en;
...@@ -522,9 +722,10 @@ BEGIN ...@@ -522,9 +722,10 @@ BEGIN
mm_adr_cnt <= TO_UINT(sla_in_ram_mosi.address(c_ram.adr_w-1 DOWNTO 0)) WHEN sla_in_ram_mosi.rd = '1'; 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'; 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(dp_pipeline_src_out_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, ram_out_same_w_r_adr) IS 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 BEGIN
IF dp_pipeline_src_out_pp.sync = '1' THEN IF g_ram_miso_sim_mode = FALSE THEN
IF snk_in_pppp.sync = '1' THEN
ram_out_wr_en <= '0'; ram_out_wr_en <= '0';
nxt_cycle_cnt <= 0; nxt_cycle_cnt <= 0;
ELSIF cycle_cnt = c_clear THEN ELSIF cycle_cnt = c_clear THEN
...@@ -544,6 +745,7 @@ BEGIN ...@@ -544,6 +745,7 @@ BEGIN
nxt_cycle_cnt <= cycle_cnt +1; nxt_cycle_cnt <= cycle_cnt +1;
ELSIF cycle_cnt > c_clear THEN ELSIF cycle_cnt > c_clear THEN
ram_out_wr_adr <= INCR_UVEC(prev_ram_out_wr_adr, 1); ram_out_wr_adr <= INCR_UVEC(prev_ram_out_wr_adr, 1);
ram_out_wr_dat <= (OTHERS => '0');
nxt_cycle_cnt <= cycle_cnt +1; nxt_cycle_cnt <= cycle_cnt +1;
IF ram_out_same_w_r_adr = '1' OR snk_in.sync = '1' THEN 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.rddata(c_ram.dat_w-1 DOWNTO 0) <= (OTHERS => '0');
...@@ -554,22 +756,38 @@ BEGIN ...@@ -554,22 +756,38 @@ BEGIN
sla_out_ram_miso.rddata(c_ram.dat_w-1 DOWNTO 0) <= ram_out_rd_dat; 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; sla_out_ram_miso.rdval <= ram_out_rd_val;
END IF; END IF;
ram_out_wr_en <= '1';
ELSIF mm_adr_illegal_pp = '1' THEN 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_adr <= sla_in_ram_mosi.address(c_ram.adr_w-1 DOWNTO 0);
ram_out_rd_en <= sla_in_ram_mosi.rd; 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.rddata(c_ram.dat_w-1 DOWNTO 0) <= (OTHERS => '0');
sla_out_ram_miso.rdval <= ram_out_rd_val; sla_out_ram_miso.rdval <= ram_out_rd_val;
nxt_cycle_cnt <= cycle_cnt +1; nxt_cycle_cnt <= cycle_cnt +1;
ram_out_wr_en <= '0';
ELSE ELSE
ram_out_rd_adr <= sla_in_ram_mosi.address(c_ram.adr_w-1 DOWNTO 0); 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; 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.rddata(c_ram.dat_w-1 DOWNTO 0) <= ram_out_rd_dat;
sla_out_ram_miso.rdval <= ram_out_rd_val; sla_out_ram_miso.rdval <= ram_out_rd_val;
nxt_cycle_cnt <= cycle_cnt +1; 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 IF;
END PROCESS; 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;
END rtl; END rtl;
...@@ -13,6 +13,7 @@ ENTITY st_histogram_8_april IS ...@@ -13,6 +13,7 @@ ENTITY st_histogram_8_april IS
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_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_bins : NATURAL := 512; -- is a power of 2 and g_nof_bins <= c_data_span; max. 512
g_nof_data : NATURAL g_nof_data : NATURAL
-- g_sim_ram_miso_mode : BOOLEAN := FALSE -- when TRUE the ram_miso bus will get a copy of the data written into the RAM.
); );
PORT ( PORT (
dp_rst : IN STD_LOGIC; dp_rst : IN STD_LOGIC;
...@@ -57,31 +58,29 @@ ARCHITECTURE rtl OF st_histogram_8_april IS ...@@ -57,31 +58,29 @@ ARCHITECTURE rtl OF st_histogram_8_april IS
SIGNAL nxt_bin_arbiter_rd_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_mosi : t_mem_mosi;
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_0_miso : t_mem_miso := c_mem_miso_rst; SIGNAL common_ram_r_w_0_miso : t_mem_miso := c_mem_miso_rst;
SIGNAL init_phase : STD_LOGIC := '1'; SIGNAL init_phase : STD_LOGIC := '1';
SIGNAL nxt_init_phase : STD_LOGIC;
SIGNAL rd_cnt_allowed : STD_LOGIC := '0'; SIGNAL rd_cnt_allowed : STD_LOGIC := '0';
SIGNAL rd_cnt_allowed_pp : STD_LOGIC := '0'; SIGNAL rd_cnt_allowed_pp : STD_LOGIC := '0';
SIGNAL nxt_rd_adr_cnt : NATURAL := 0;
SIGNAL rd_adr_cnt : NATURAL;-- := 0;
SIGNAL toggle_detect : STD_LOGIC := '0'; SIGNAL toggle_detect : STD_LOGIC := '0';
SIGNAL toggle_detect_pp : STD_LOGIC; SIGNAL toggle_detect_pp : STD_LOGIC;
SIGNAL toggle_detect_false : STD_LOGIC := '1'; SIGNAL toggle_detect_false : STD_LOGIC := '1';
-- SIGNAL nxt_toggle_adr_cnt : NATURAL := 0;
-- SIGNAL toggle_adr_cnt : NATURAL;-- := 0;
SIGNAL nxt_prev_wrdata : NATURAL; SIGNAL nxt_prev_wrdata : NATURAL;
SIGNAL prev_wrdata : NATURAL; SIGNAL prev_wrdata : NATURAL;
SIGNAL prev_prev_wrdata : NATURAL; SIGNAL prev_prev_wrdata : NATURAL;
SIGNAL prev_prev_prev_wrdata: NATURAL; SIGNAL prev_prev_prev_wrdata: NATURAL;
SIGNAL sync_detect : STD_LOGIC := '0'; SIGNAL sync_detect : STD_LOGIC := '0';
SIGNAL sync_detect_pp : STD_LOGIC; SIGNAL sync_detect_pp : STD_LOGIC;
-- SIGNAL adr_w : STD_LOGIC_VECTOR(g_in_data_w -1 DOWNTO c_adr_low);
SIGNAL same_r_w_address : STD_LOGIC; SIGNAL same_r_w_address : STD_LOGIC;
SIGNAL same_r_w_address_pp : STD_LOGIC; SIGNAL same_r_w_address_pp : STD_LOGIC;
--pipelined signals --pipelined signals
SIGNAL dp_pipeline_src_out_p : t_dp_sosi; SIGNAL snk_in_p : t_dp_sosi;
SIGNAL dp_pipeline_src_out_pp : t_dp_sosi; SIGNAL snk_in_pp : t_dp_sosi;
SIGNAL prev_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_pp : t_mem_mosi := c_mem_mosi_rst;
SIGNAL bin_reader_mosi_ppp : t_mem_mosi := c_mem_mosi_rst; SIGNAL bin_reader_mosi_ppp : t_mem_mosi := c_mem_mosi_rst;
...@@ -97,15 +96,27 @@ BEGIN ...@@ -97,15 +96,27 @@ BEGIN
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
-- Bin reader: Convert snk_in data to bin_reader_mosi with read request -- 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) -- . in : snk_in (latency: 0)
-- . out : bin_reader_mosi (latency: 0) -- : bin_arbiter_rd_miso (latency: 2)
-- . out : bin_reader_mosi_pp (latency: 2) -- . out : init_phase (latency: 0 ?
-- - out : rd_cnt_allowed_pp (latency: 2) -- : 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.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_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 --snk_in pipeline; Enable sync and valid comparisons
u_dp_pipeline_snk_in_1_cycle : ENTITY dp_lib.dp_pipeline u_dp_pipeline_snk_in_1_cycle : ENTITY dp_lib.dp_pipeline
GENERIC MAP ( GENERIC MAP (
g_pipeline => 1 -- 0 for wires, > 0 for registers, g_pipeline => 1 -- 0 for wires, > 0 for registers,
...@@ -114,11 +125,22 @@ BEGIN ...@@ -114,11 +125,22 @@ BEGIN
rst => dp_rst, rst => dp_rst,
clk => dp_clk, clk => dp_clk,
snk_in => snk_in, snk_in => snk_in,
src_out => dp_pipeline_src_out_p src_out => snk_in_p
); );
init_phase <= '0' WHEN dp_pipeline_src_out_p.sync = '1'; 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_p_.sync='1' ELSE init_phase;
-- p_init_phase : PROCESS(dp_clk, dp_rst)
-- BEGIN
-- IF dp_rst = '1' THEN
-- init_phase <= '1';
-- ELSIF RISING_EDGE(dp_clk) THEN
-- init_phase <= nxt_init_phase;
-- END IF;
-- END PROCESS;
-- Enable sync comparisons
u_dp_pipeline_snk_in_2_cycle : ENTITY dp_lib.dp_pipeline u_dp_pipeline_snk_in_2_cycle : ENTITY dp_lib.dp_pipeline
GENERIC MAP ( GENERIC MAP (
g_pipeline => 2 -- 0 for wires, > 0 for registers, g_pipeline => 2 -- 0 for wires, > 0 for registers,
...@@ -127,25 +149,15 @@ BEGIN ...@@ -127,25 +149,15 @@ BEGIN
rst => dp_rst, rst => dp_rst,
clk => dp_clk, clk => dp_clk,
snk_in => snk_in, snk_in => snk_in,
src_out => dp_pipeline_src_out_pp src_out => snk_in_pp
); );
dbg_snk_data <= dp_pipeline_src_out_pp.data(g_in_data_w-1 DOWNTO 0); dbg_snk_data <= snk_in_pp.data(g_in_data_w-1 DOWNTO 0);
toggle_detect_false <= '0' WHEN dp_pipeline_src_out_pp.sync = '1';
sync_detect <= snk_in.valid WHEN (snk_in.sync='1' OR dp_pipeline_src_out_p.sync='1' OR dp_pipeline_src_out_pp.sync='1') ELSE '0';
-- u_dp_sync_detect_3_cycle : ENTITY dp_lib.dp_pipeline 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
-- GENERIC MAP ( 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
-- g_pipeline => 3 -- 0 for wires, > 0 for registers,
-- )
-- PORT MAP (
-- rst => dp_rst,
-- clk => dp_clk,
-- snk_in => sync_detect,
-- src_out => sync_detect_ppp
-- );
-- Line up to p_nxt_bin_writer_mosi process
u_common_pipeline_sl_sync_detect_2_cycle : ENTITY common_lib.common_pipeline_sl u_common_pipeline_sl_sync_detect_2_cycle : ENTITY common_lib.common_pipeline_sl
GENERIC MAP( GENERIC MAP(
g_pipeline => 2 -- 0 for wires, > 0 for registers, g_pipeline => 2 -- 0 for wires, > 0 for registers,
...@@ -156,19 +168,8 @@ BEGIN ...@@ -156,19 +168,8 @@ BEGIN
out_dat => sync_detect_pp out_dat => sync_detect_pp
); );
--prev_bin_reader_mosi pipeline -- Enable adress comparisons 1 cycle back
-- u_dp_pipeline_bin_reader_mosi_1_cycle : ENTITY dp_lib.dp_pipeline -- Skip unvalid data with trigger bin_reader_mosi.rd to make comparisons between unvalid-data-seperated data possible.
-- GENERIC MAP (
-- g_pipeline => 1 -- 0 for wires, > 0 for registers,
-- )
-- PORT MAP (
-- rst => dp_rst,
-- clk => dp_clk,
-- snk_in => bin_reader_mosi,
-- src_out => prev_bin_reader_mosi
-- );
u_common_pipeline_bin_reader_mosi_1_cycle : ENTITY common_lib.common_pipeline u_common_pipeline_bin_reader_mosi_1_cycle : ENTITY common_lib.common_pipeline
GENERIC MAP ( GENERIC MAP (
g_representation => "UNSIGNED", --orig. signed g_representation => "UNSIGNED", --orig. signed
...@@ -183,7 +184,8 @@ BEGIN ...@@ -183,7 +184,8 @@ BEGIN
out_dat => prev_bin_reader_mosi.address(c_adr_w-1 DOWNTO 0) out_dat => prev_bin_reader_mosi.address(c_adr_w-1 DOWNTO 0)
); );
u_common_pipeline_bin_reader_mosi_2_cycle : ENTITY common_lib.common_pipeline -- better to pipeline prev_bin_reader_mosi?? -- Enable adress comparisons 2 cycles back
u_common_pipeline_bin_reader_mosi_2_cycle : ENTITY common_lib.common_pipeline
GENERIC MAP ( GENERIC MAP (
g_representation => "UNSIGNED", --orig. signed g_representation => "UNSIGNED", --orig. signed
g_pipeline => 1, g_pipeline => 1,
...@@ -196,7 +198,8 @@ BEGIN ...@@ -196,7 +198,8 @@ BEGIN
out_dat => bin_reader_mosi_pp.address(c_adr_w-1 DOWNTO 0) out_dat => bin_reader_mosi_pp.address(c_adr_w-1 DOWNTO 0)
); );
u_common_pipeline_bin_reader_mosi_3_cycle : ENTITY common_lib.common_pipeline -- better to pipeline prev_bin_reader_mosi?? -- Enable adress comparisons 3 cycles back
u_common_pipeline_bin_reader_mosi_3_cycle : ENTITY common_lib.common_pipeline
GENERIC MAP ( GENERIC MAP (
g_representation => "UNSIGNED", --orig. signed g_representation => "UNSIGNED", --orig. signed
g_pipeline => 2, g_pipeline => 2,
...@@ -210,24 +213,12 @@ BEGIN ...@@ -210,24 +213,12 @@ BEGIN
); );
--bin_reader_mosi_pp pipeline -- 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
-- u_dp_pipeline_bin_reader_mosi_2_cycle : ENTITY dp_lib.dp_pipeline 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') ) )
-- GENERIC MAP ( OR (bin_reader_mosi.address = prev_bin_reader_mosi.address AND init_phase='0' AND sync_detect='0')
-- g_pipeline => 2 -- 0 for wires, > 0 for registers,
-- )
-- PORT MAP (
-- rst => dp_rst,
-- clk => dp_clk,
-- snk_in => bin_reader_mosi,
-- src_out => bin_reader_mosi_pp
-- );
-- rd_cnt_allowed <= snk_in.valid WHEN (bin_reader_mosi.address = prev_bin_reader_mosi.address AND init_phase = '0') ELSE '0'; -- AND snk_in.sync='0'
rd_cnt_allowed <= snk_in.valid WHEN ( bin_reader_mosi.address = prev_bin_reader_mosi.address AND ( (dp_pipeline_src_out_p.sync='1' AND dp_pipeline_src_out_p.valid='1') OR (dp_pipeline_src_out_pp.sync='1' AND dp_pipeline_src_out_p.valid='1') ) )
ELSE snk_in.valid WHEN (bin_reader_mosi.address = prev_bin_reader_mosi.address AND init_phase='0' AND snk_in.sync='0')
ELSE '0'; ELSE '0';
--rd_cnt_allowed_pp pipeline -- 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 u_common_pipeline_sl_rd_cnt_allowed : ENTITY common_lib.common_pipeline_sl
GENERIC MAP( GENERIC MAP(
g_pipeline => 2 -- 0 for wires, > 0 for registers, g_pipeline => 2 -- 0 for wires, > 0 for registers,
...@@ -238,8 +229,12 @@ BEGIN ...@@ -238,8 +229,12 @@ BEGIN
out_dat => rd_cnt_allowed_pp out_dat => rd_cnt_allowed_pp
); );
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') ELSE '0'; --AND (snk_in.sync='0' OR dp_pipeline_src_out_p.sync='0') -- 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 u_common_pipeline_sl_toggle_detect : ENTITY common_lib.common_pipeline_sl
GENERIC MAP( GENERIC MAP(
g_pipeline => 2 -- 0 for wires, > 0 for registers, g_pipeline => 2 -- 0 for wires, > 0 for registers,
...@@ -250,8 +245,10 @@ BEGIN ...@@ -250,8 +245,10 @@ BEGIN
out_dat => toggle_detect_pp 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'; 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 u_common_pipeline_sl_same_r_w_address : ENTITY common_lib.common_pipeline_sl
GENERIC MAP( GENERIC MAP(
g_pipeline => 2 -- 0 for wires, > 0 for registers, g_pipeline => 2 -- 0 for wires, > 0 for registers,
...@@ -265,55 +262,44 @@ BEGIN ...@@ -265,55 +262,44 @@ BEGIN
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
-- Bin writer : increments current bin value and sets up write request -- Bin writer : increments current bin value and sets up write request
-- . in : dp_pipeline_src_out_pp (latency: 2)
-- . in : toggle_detect_pp (latency: 2) -- . in : toggle_detect_pp (latency: 2)
-- . in : same_r_w_address_pp (latency: 2) -- . in : same_r_w_address_pp (latency: 2)
-- . in : bin_reader_mosi_pp (latency: 2) -- . in : bin_reader_mosi_pp (latency: 2)
-- . in : common_ram_r_w_0_miso (latency: 2) -- . in : bin_reader_rd_miso (latency: 2) aka bin_arbiter_rd_miso or common_ram_r_w_0_miso
-- . in : rd_cnt_allowed_pp (latency: 2) -- . in : rd_cnt_allowed_pp (latency: 2)
-- . in : sync_detect_pp
-- . out : bin_writer_mosi (latency: 3) -- . out : bin_writer_mosi (latency: 3)
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
p_nxt_bin_writer_mosi : PROCESS(common_ram_r_w_0_miso, common_ram_r_w_0_miso.rdval, common_ram_r_w_0_miso.rddata, p_nxt_bin_writer_mosi : PROCESS(bin_reader_rd_miso,
bin_reader_mosi_pp.address, toggle_detect, rd_cnt_allowed_pp, rd_adr_cnt, init_phase, prev_wrdata, prev_prev_wrdata, sync_detect_pp, same_r_w_address_pp, dp_pipeline_src_out_pp.valid) IS bin_reader_mosi_pp.address, toggle_detect_pp, rd_cnt_allowed_pp, init_phase, prev_wrdata, prev_prev_wrdata, prev_prev_prev_wrdata, sync_detect_pp, same_r_w_address_pp) IS -- init_phase unnecesary? ; removed: common_ram_r_w_0_miso.rdval, common_ram_r_w_0_miso.rddata,
BEGIN BEGIN
nxt_bin_writer_mosi <= c_mem_mosi_rst; nxt_bin_writer_mosi <= c_mem_mosi_rst;
dbg_state_string <= "unv"; dbg_state_string <= "unv";
IF common_ram_r_w_0_miso.rdval='1' THEN -- OR rd_cnt_allowed_pp = '1' -- when not same as last 2 adresses IF bin_reader_rd_miso.rdval='1' THEN -- common_ram_r_w_0_miso
nxt_bin_writer_mosi.wr <= '1'; nxt_bin_writer_mosi.wr <= '1';
nxt_bin_writer_mosi.wrdata <= INCR_UVEC(common_ram_r_w_0_miso.rddata, 1); -- c_word_w); -- depends on count case -- rd_adr_cnt nxt_bin_writer_mosi.wrdata <= INCR_UVEC(bin_reader_rd_miso.rddata, 1); -- common_ram_r_w_0_miso
nxt_bin_writer_mosi.address <= bin_reader_mosi_pp.address; --TODO: what other input do we need for this? -- becomes bin_reader_mosi.address nxt_bin_writer_mosi.address <= bin_reader_mosi_pp.address;
-- reset count? if toggle detected copy count to toggle counter nxt_prev_wrdata <= TO_UINT(bin_reader_rd_miso.rddata) + 1; -- common_ram_r_w_0_miso
nxt_prev_wrdata <= TO_UINT(common_ram_r_w_0_miso.rddata) + 1;
-- nxt_rd_adr_cnt <= 0; -- really necessary ??
dbg_state_string <= "val"; dbg_state_string <= "val";
-- IF bin_reader_mosi_pp.address = bin_reader_mosi.address THEN -- Double implemented ?? toggle?
-- nxt_toggle_adr_cnt <= INCR_UVEC(common_ram_r_w_0_miso.rddata, 1); -- Double implemented ?? ELSIF toggle_detect_pp = '1' THEN
ELSIF toggle_detect_pp = '1' THEN -- dp_pipeline_src_out_pp: 2
nxt_bin_writer_mosi.wr <= '1'; nxt_bin_writer_mosi.wr <= '1';
nxt_bin_writer_mosi.wrdata <= TO_UVEC( (prev_prev_wrdata+1), c_mem_data_w); -- prev_wrdata + rd_adr_cnt + toggle_adr_cnt??? + 1 òf prev_prev_wrdata + 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_bin_writer_mosi.address <= bin_reader_mosi_pp.address;
-- nxt_toggle_adr_cnt <= 0;
nxt_prev_wrdata <= prev_prev_wrdata+1; nxt_prev_wrdata <= prev_prev_wrdata+1;
dbg_state_string <= "td "; dbg_state_string <= "td ";
ELSIF rd_cnt_allowed_pp = '1' THEN ELSIF rd_cnt_allowed_pp = '1' THEN
-- nxt_rd_adr_cnt <= rd_adr_cnt + 1; -- << !! is rd_adr_cnt really necessary? prev_wrdata might fulfill the need !!
nxt_bin_writer_mosi.wr <= '1'; nxt_bin_writer_mosi.wr <= '1';
-- IF sync_detect_ppp = '1' THEN nxt_bin_writer_mosi.wrdata <= TO_UVEC( (prev_wrdata + 1), c_mem_data_w);
-- nxt_bin_writer_mosi.wrdata <= TO_UVEC( (rd_adr_cnt + 1), c_mem_data_w); -- snk_in.sync (impossible); dp_pipeline_src_out_p (thus 1st cnt): 2 (cnt+1?); dp_pipeline_src_out_pp (1st or maybe 2nd cnt): cnt+1
-- dbg_state_string <= "rs ";
-- ELSE
nxt_bin_writer_mosi.wrdata <= TO_UVEC( (prev_wrdata + rd_adr_cnt + 1), c_mem_data_w); -- c_word_w); -- maybe RAM + cnt + 1 ?? -- only prev_wrdata + 1 necessary
nxt_prev_wrdata <= prev_wrdata + 1; nxt_prev_wrdata <= prev_wrdata + 1;
dbg_state_string <= "r# "; dbg_state_string <= "r# ";
-- END IF;
nxt_bin_writer_mosi.address <= bin_reader_mosi_pp.address; nxt_bin_writer_mosi.address <= bin_reader_mosi_pp.address;
ELSIF sync_detect_pp = '1' THEN -- snk_in.sync at least -- good as it is! ELSIF sync_detect_pp = '1' THEN
nxt_bin_writer_mosi.wr <= '1'; nxt_bin_writer_mosi.wr <= '1';
nxt_bin_writer_mosi.wrdata <= TO_UVEC(1, c_mem_data_w); -- snk_in.sync: 1; dp_pipeline_src_out_p.sync (thus new adress): 1; dp_pipeline_src_out_pp.sync (thus new adress): 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_bin_writer_mosi.address <= bin_reader_mosi_pp.address;
-- nxt_rd_adr_cnt <= 0; -- really necessary ??
nxt_prev_wrdata <= 1; nxt_prev_wrdata <= 1;
dbg_state_string <= "sd "; dbg_state_string <= "sd ";
...@@ -326,37 +312,59 @@ BEGIN ...@@ -326,37 +312,59 @@ BEGIN
END IF; END IF;
END PROCESS; END PROCESS;
p_bin_writer_mosi : PROCESS(dp_clk, dp_rst, nxt_bin_writer_mosi, nxt_rd_adr_cnt, nxt_prev_wrdata, prev_wrdata, prev_prev_wrdata) IS 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 BEGIN
IF dp_rst = '1' THEN IF dp_rst = '1' THEN
bin_writer_mosi <= c_mem_mosi_rst; prev_wrdata <= 0;
ELSIF RISING_EDGE(dp_clk) THEN prev_prev_wrdata <= 0;
bin_writer_mosi <= nxt_bin_writer_mosi; prev_prev_prev_wrdata <= 0;
-- rd_adr_cnt <= nxt_rd_adr_cnt; ELSIF nxt_bin_writer_mosi.wr='1' AND RISING_EDGE(dp_clk) THEN
-- toggle_adr_cnt <= nxt_toggle_adr_cnt;
prev_wrdata <= nxt_prev_wrdata; prev_wrdata <= nxt_prev_wrdata;
prev_prev_wrdata <= prev_wrdata; prev_prev_wrdata <= prev_wrdata;
prev_prev_prev_wrdata <= prev_prev_wrdata; prev_prev_prev_wrdata <= prev_prev_wrdata;
END IF; END IF;
END PROCESS; END PROCESS;
p_bin_writer_mosi : PROCESS(dp_clk, dp_rst) IS --, nxt_bin_writer_mosi, nxt_prev_wrdata, prev_wrdata, prev_prev_wrdata
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;
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;
END IF;
END PROCESS;
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
-- Bin Arbiter: Determine next RAM access -- Bin Arbiter: Determine next RAM access
-- . in : bin_reader_mosi (latency: 0) -- . in : bin_reader_mosi (latency: 0)
-- : init_phase (latency: 0) -- : init_phase (latency: 0)
-- : prev_bin_reader_mosi (latency: 1) -- : prev_bin_reader_mosi (latency: 1)
-- : bin_reader_mosi_pp (latency: 2)
-- : bin_reader_mosi_ppp (latency: 3)
-- : bin_writer_mosi (latency: 3) -- : bin_writer_mosi (latency: 3)
-- : sync_detect (latency: 0? or 3?
-- : common_ram_r_w_0_miso (latency: 2)
-- . out : bin_arbiter_rd_mosi (latency: 1) -- . out : bin_arbiter_rd_mosi (latency: 1)
-- . : bin_arbiter_rd_miso (latency: 2)
-- . : bin_arbiter_wr_mosi (latency: 4) -- . : bin_arbiter_wr_mosi (latency: 4)
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
nxt_bin_arbiter_wr_mosi <= bin_writer_mosi; --TODO - The rd and wr mosi should not have the same address. v met 2 cycles rd mag, met 3 cycles niet, dus klopt dit wel?, moet hier niet bin_reader_mosi_pp staan? --AND !(A=B) nxt_bin_arbiter_wr_mosi <= bin_writer_mosi;
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) ) -- 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.
-- AND sync_detect='0') 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
OR (init_phase = '1') ELSE '0'; -- bin_writer_mosi(adress 3cycles ago?) .address when .rd='1' ???? 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; nxt_bin_arbiter_rd_mosi.address <= bin_reader_mosi.address;
p_bin_arbiter_mosi : PROCESS(dp_clk, dp_rst, nxt_bin_arbiter_wr_mosi, nxt_bin_arbiter_rd_mosi) IS p_bin_arbiter_mosi : PROCESS(dp_clk, dp_rst) IS --, nxt_bin_arbiter_wr_mosi, nxt_bin_arbiter_rd_mosi
BEGIN BEGIN
IF dp_rst = '1' THEN IF dp_rst = '1' THEN
bin_arbiter_wr_mosi <= c_mem_mosi_rst; bin_arbiter_wr_mosi <= c_mem_mosi_rst;
...@@ -367,6 +375,12 @@ BEGIN ...@@ -367,6 +375,12 @@ BEGIN
END IF; END IF;
END PROCESS; END PROCESS;
-- Temporary debug data
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_0_miso;
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
-- RAM that contains the bins -- RAM that contains the bins
......
...@@ -29,23 +29,31 @@ ...@@ -29,23 +29,31 @@
-- to generate data that can make related problems with that vissible. -- to generate data that can make related problems with that vissible.
-- --
-- To know if there can constantly new data be witten to the RAM blocks -- To know if there can constantly new data be witten to the RAM blocks
-- a simple counter is sufficient. -- a counter would be sufficient.
-- --
-- Because there is a delay between requesting and writing back of data of -- Because there is a delay between requesting and writing back of data of
-- 2 cycles and it is illegal to read and write on the same adres at the -- 3 cycles and it is illegal to read and write on the same adres at the
-- same time, a special situation can happen where the addresses can toggle -- same time, there are 2 special situations that can happen. One where the
-- (e.g. 0; 1; 0; 1) which causes incorrect counting. To simulate this the -- addresses can toggle (e.g. 0; 1; 0; 1) and one where a simultanious read
-- g_snk_in_data_sim_type can be set to 'toggle' -- and write are triggered (e.g. 0; 1; 1; 0). Both would cause incorrect
-- counting as the address count can't be updated (written) before it's
-- address is requested again. Due to this the counter in st_histogram can
-- not be a simple counter that only counts and compares on repeating
-- addresses. It also has to compare on 2 and 3 cycles back - which makes
-- it complicated enough that it requires additional test stimuli.
-- To simulate with the required stimuli the g_snk_in_data_sim_type can be
-- set to 'counter', 'toggle', 'same rw' or a 'mix' of it.
-- --
-- Only incoming data while snk_in.valid = '1' may be counted. To keep the -- Only incoming data while snk_in.valid = '1' may be counted. To keep the
-- simulation simple there is the option to let there be some gap's in the -- simulation simple there is the option to let there be some gap's in the
-- valid data (or not) where snk_in.valid = '0' by setting the g_valid_gap -- valid data (or not) where snk_in.valid = '0' by setting the g_valid_gap
-- to TRUE or FALSE. -- to 'true', 'false' or 'custom'.
-- --
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
LIBRARY IEEE, common_lib, mm_lib, dp_lib; LIBRARY IEEE, common_lib, mm_lib, dp_lib;
USE IEEE.std_logic_1164.ALL; USE IEEE.std_logic_1164.ALL;
USE IEEE.numeric_std.ALL; -- needed by TO_UNSIGNED
USE common_lib.common_pkg.ALL; USE common_lib.common_pkg.ALL;
USE common_lib.common_mem_pkg.ALL; USE common_lib.common_mem_pkg.ALL;
USE common_lib.tb_common_pkg.ALL; USE common_lib.tb_common_pkg.ALL;
...@@ -59,8 +67,8 @@ ENTITY tb_st_histogram IS ...@@ -59,8 +67,8 @@ ENTITY tb_st_histogram IS
g_nof_bins : NATURAL := 8; --8 ; 2 g_nof_bins : NATURAL := 8; --8 ; 2
g_nof_data : NATURAL := 200; g_nof_data : NATURAL := 200;
--g_str : STRING := "freq.density"; --g_str : STRING := "freq.density";
g_valid_gap : BOOLEAN := TRUE; g_valid_gap : STRING := "custom"; -- "false" or "true" or "custom" --BOOLEAN := TRUE
g_snk_in_data_sim_type : STRING := "counter" -- "counter" or "toggle" or "same rw" or "mix" g_snk_in_data_sim_type : STRING := "same rw" -- "counter" or "toggle" or "same rw" or "mix"
); );
END tb_st_histogram; END tb_st_histogram;
...@@ -79,6 +87,7 @@ ARCHITECTURE tb OF tb_st_histogram IS ...@@ -79,6 +87,7 @@ ARCHITECTURE tb OF tb_st_histogram IS
SIGNAL prev_unvalid : STD_LOGIC := '0'; SIGNAL prev_unvalid : STD_LOGIC := '0';
SIGNAL init_phase : STD_LOGIC := '1'; SIGNAL init_phase : STD_LOGIC := '1';
SIGNAL toggle_start : STD_LOGIC := '0'; SIGNAL toggle_start : STD_LOGIC := '0';
SIGNAL pre_sync : STD_LOGIC := '0';
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
...@@ -87,10 +96,26 @@ ARCHITECTURE tb OF tb_st_histogram IS ...@@ -87,10 +96,26 @@ ARCHITECTURE tb OF tb_st_histogram IS
TYPE t_srw_arr IS ARRAY (NATURAL RANGE <>) OF INTEGER; TYPE t_srw_arr IS ARRAY (NATURAL RANGE <>) OF INTEGER;
CONSTANT c_srw_arr : t_srw_arr := (0,0,1,1,0,0,1,2,3, 1, 2, 3, 0, 3, 3, 0, 3); CONSTANT c_srw_arr : t_srw_arr := (0,0,1,1,0,0,1,2,3, 1, 2, 3, 0, 3, 3, 0, 3);
-- 1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17 -- 1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17
--0:1.2. 3.4. 05. 06.
--1: 1.2. 3. 04.
--2: 1. 02.
--3: 1. 02. 03.04. 05.
--srw: x. x. x. x. x. x. x. u.
SIGNAL srw_index_cnt : NATURAL := 0; SIGNAL srw_index_cnt : NATURAL := 0;
----------------------------------------------------------------------------
-- Valid stimuli
----------------------------------------------------------------------------
TYPE t_val_arr IS ARRAY (NATURAL RANGE <>) OF INTEGER;
CONSTANT c_val_arr : t_val_arr := (1,1,1,1,0,1,1,1,1, 1, 1, 1, 1, 0, 1, 1, 1);
-- 1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17
SIGNAL val_index_cnt : NATURAL := 0;
SIGNAL dbg_valid : NATURAL;
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
-- Clocks and resets -- Clocks and resets
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
...@@ -109,6 +134,34 @@ ARCHITECTURE tb OF tb_st_histogram IS ...@@ -109,6 +134,34 @@ ARCHITECTURE tb OF tb_st_histogram IS
SIGNAL st_histogram_snk_in : t_dp_sosi; SIGNAL st_histogram_snk_in : t_dp_sosi;
----------------------------------------------------------------------------
-- Streaming Output
----------------------------------------------------------------------------
SIGNAL st_histogram_ram_miso : t_mem_miso;
SIGNAL st_histogram_dbg_ram_miso : t_mem_miso;
----------------------------------------------------------------------------
-- Self check array
----------------------------------------------------------------------------
TYPE t_data_check_arr IS ARRAY (0 TO g_nof_bins) OF INTEGER;
SIGNAL data_check_arr : t_data_check_arr := (OTHERS=> 0);
SIGNAL check_adr : NATURAL := 0;
SIGNAL prev_check_adr : NATURAL;
SIGNAL nxt_check_arr_cnt : NATURAL;
SIGNAL st_histogram_snk_in_ppp : t_dp_sosi;
SIGNAL st_histogram_snk_in_pppp: t_dp_sosi;
-- SIGNAL dbg_check_adr :STD_LOGIC_VECTOR(g_data_w-1 DOWNTO c_adr_low); -- : NATURAL;
SIGNAL dbg_error_location : STD_LOGIC;
SIGNAL error_cnt : NATURAL;
SIGNAL dbg_int_data_miso : NATURAL;
SIGNAL dbg_int_data_arr : NATURAL;
BEGIN BEGIN
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
...@@ -122,7 +175,7 @@ BEGIN ...@@ -122,7 +175,7 @@ BEGIN
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
-- Source: stimuli -- Source: stimuli
-- st_histogram_snk_in.data counter or toggle stimuli -- st_histogram_snk_in.data counter or toggle or same_rw stimuli
-- .valid with or without gap's in valid stimuli -- .valid with or without gap's in valid stimuli
-- .sync sync stimuli -- .sync sync stimuli
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
...@@ -162,7 +215,7 @@ BEGIN ...@@ -162,7 +215,7 @@ BEGIN
ELSIF g_snk_in_data_sim_type = "same rw" THEN ELSIF g_snk_in_data_sim_type = "same rw" THEN
IF dp_rst='1' THEN IF dp_rst='1' THEN
st_histogram_snk_in.data(g_data_w-1 DOWNTO 0) <= (OTHERS=>'0'); st_histogram_snk_in.data(g_data_w-1 DOWNTO 0) <= (OTHERS=>'0');
ELSIF rising_edge(dp_clk) AND pre_valid='1' THEN -- AND init_phase='0' didn't work ELSIF rising_edge(dp_clk) AND pre_sync='1' THEN -- AND init_phase='0' didn't work
st_histogram_snk_in.data(g_data_w-1 DOWNTO c_adr_low) <= TO_UVEC(c_srw_arr(srw_index_cnt), c_adr_w); --placeholder ! st_histogram_snk_in.data(g_data_w-1 DOWNTO c_adr_low) <= TO_UVEC(c_srw_arr(srw_index_cnt), c_adr_w); --placeholder !
IF srw_index_cnt = c_srw_arr'LENGTH -1 THEN IF srw_index_cnt = c_srw_arr'LENGTH -1 THEN
srw_index_cnt <= 0; srw_index_cnt <= 0;
...@@ -209,7 +262,7 @@ BEGIN ...@@ -209,7 +262,7 @@ BEGIN
p_stimuli : PROCESS p_stimuli : PROCESS
BEGIN BEGIN
IF g_valid_gap = FALSE THEN IF g_valid_gap = "false" THEN
-- initializing -- initializing
st_histogram_snk_in.sync <= '0'; st_histogram_snk_in.sync <= '0';
...@@ -233,13 +286,15 @@ BEGIN ...@@ -233,13 +286,15 @@ BEGIN
tb_end <= '1'; tb_end <= '1';
WAIT; WAIT;
ELSIF g_valid_gap = TRUE THEN ELSIF g_valid_gap = "true" THEN
-- initializing -- initializing
st_histogram_snk_in.sync <= '0'; st_histogram_snk_in.sync <= '0';
st_histogram_snk_in.valid <= '0'; st_histogram_snk_in.valid <= '0';
WAIT UNTIL rising_edge(dp_clk); WAIT UNTIL rising_edge(dp_clk);
FOR I IN 0 TO 9 LOOP WAIT UNTIL rising_edge(dp_clk); END LOOP; FOR I IN 0 TO 8 LOOP WAIT UNTIL rising_edge(dp_clk); END LOOP;
pre_sync <= '1';
WAIT UNTIL rising_edge(dp_clk);
pre_valid <= '1'; pre_valid <= '1';
st_histogram_snk_in.valid <= '1'; st_histogram_snk_in.valid <= '1';
-- generating g_nof_sync-1 sync pulses with gaps in 'valid' -- generating g_nof_sync-1 sync pulses with gaps in 'valid'
...@@ -264,7 +319,7 @@ BEGIN ...@@ -264,7 +319,7 @@ BEGIN
WAIT UNTIL rising_edge(dp_clk); WAIT UNTIL rising_edge(dp_clk);
st_histogram_snk_in.valid <= '0'; st_histogram_snk_in.valid <= '0';
WAIT UNTIL rising_edge(dp_clk); WAIT UNTIL rising_edge(dp_clk);
--st_histogram_snk_in.valid <= '0'; -- gap while sync --st_histogram_snk_in.valid <= '0'; -- gap while sync --should not happen, impossible
st_histogram_snk_in.sync <= '1'; st_histogram_snk_in.sync <= '1';
pre_valid <= '1'; pre_valid <= '1';
WAIT UNTIL rising_edge(dp_clk); WAIT UNTIL rising_edge(dp_clk);
...@@ -276,21 +331,66 @@ BEGIN ...@@ -276,21 +331,66 @@ BEGIN
FOR I IN 0 TO 9 LOOP WAIT UNTIL rising_edge(dp_clk); END LOOP; FOR I IN 0 TO 9 LOOP WAIT UNTIL rising_edge(dp_clk); END LOOP;
tb_end <= '1'; tb_end <= '1';
WAIT; WAIT;
ELSIF g_valid_gap = "custom" THEN
-- initializing
st_histogram_snk_in.sync <= '0';
st_histogram_snk_in.valid <= '0';
WAIT UNTIL rising_edge(dp_clk);
FOR I IN 0 TO 8 LOOP WAIT UNTIL rising_edge(dp_clk); END LOOP;
pre_sync <= '1';
WAIT UNTIL rising_edge(dp_clk);
pre_valid <= '1';
-- st_histogram_snk_in.valid <= '1';
-- generating g_nof_sync-1 sync pulses with gaps in 'valid'
FOR I IN 0 TO g_nof_sync-2 LOOP
toggle_start <= '1';
st_histogram_snk_in.sync <= '1';
st_histogram_snk_in.valid <= STD_LOGIC( TO_UNSIGNED(c_val_arr(0),1)(0) ); -- TO_UVEC(c_val_arr(0), c_adr_w); --placeholder !
WAIT UNTIL rising_edge(dp_clk);
st_histogram_snk_in.sync <= '0';
FOR I IN 1 TO c_val_arr'LENGTH -1 LOOP
st_histogram_snk_in.valid <= STD_LOGIC( TO_UNSIGNED( c_val_arr(I) ,1)(0) ); -- TO_UVEC(c_val_arr(J), c_adr_w);
dbg_valid <= I;
WAIT UNTIL rising_edge(dp_clk);
END LOOP;
proc_common_wait_some_cycles(dp_clk, (g_sync_length - (c_val_arr'LENGTH -2) )); --the -2 has to be ditched as the sync happens 2 cycles to soon
END LOOP;
-- ending
FOR I IN 0 TO 9 LOOP WAIT UNTIL rising_edge(dp_clk); END LOOP;
tb_end <= '1';
WAIT;
END IF; END IF;
END PROCESS; END PROCESS;
-- p_mm_stimuli : PROCESS --(st_histogram_snk_in.sync)
-- BEGIN
-- st_histogram_ram_mosi <= c_mem_mosi_rst; --.address(c_adr_w-1 DOWNTO 0) <= (OTHERS=>'0');
-- WAIT UNTIL st_histogram_snk_in.sync = '1';
-- -- wait till one RAM block is written
-- FOR I IN 0 TO (g_sync_length) LOOP WAIT UNTIL rising_edge(dp_clk); END LOOP;
-- -- wait for some more cycles
-- FOR I IN 0 TO 2 LOOP WAIT UNTIL rising_edge(dp_clk); END LOOP;
-- -- read all bins
-- FOR I IN 0 TO g_nof_bins-1 LOOP
-- proc_mem_mm_bus_rd(I, dp_clk, st_histogram_ram_mosi);
-- proc_common_wait_some_cycles(dp_clk, 1);
-- END LOOP;
-- END PROCESS;
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
-- DUT: Device Under Test -- DUT: Device Under Test
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
u_st_histogram : ENTITY work.st_histogram_8_april u_st_histogram : ENTITY work.st_histogram --_8_april
GENERIC MAP( GENERIC MAP(
g_in_data_w => g_data_w, g_in_data_w => g_data_w,
g_nof_bins => g_nof_bins, g_nof_bins => g_nof_bins,
g_nof_data => g_nof_data g_nof_data => g_nof_data,
--g_str => g_str g_ram_miso_sim_mode => FALSE -- TRUE
) )
PORT MAP ( PORT MAP (
dp_rst => dp_rst, dp_rst => dp_rst,
...@@ -300,8 +400,141 @@ BEGIN ...@@ -300,8 +400,141 @@ BEGIN
snk_in => st_histogram_snk_in, snk_in => st_histogram_snk_in,
-- Memory Mapped -- Memory Mapped
ram_mosi => c_mem_mosi_rst,-- sla_in_ sla_in_ram_mosi => c_mem_mosi_rst,-- sla_in_
ram_miso => OPEN -- sla_out_ sla_out_ram_miso => st_histogram_ram_miso, --OPEN -- sla_out_
dbg_ram_miso => st_histogram_dbg_ram_miso
);
----------------------------------------------------------------------------
-- Selfcheck:
-- The selfcheck is done by counting the adresses created from 3 cycles
-- delayed snk_in data into an address separated array (when in the array,
-- the data is 4 cycles delayed). This data is used as reference for
-- comparing it with the data written into a RAM block in st_histogram.
-- Because the data in st_histogram is written 4 cycles later than it got
-- in, both data are in sync and can be compared directly.
-- When the data is valid but is not the same as the reference data the
-- debug signal dbg_error_location becomes '1' so the location can be
-- easily spotted in the wave window and a report is made.
----------------------------------------------------------------------------
u_dp_pipeline_st_histogram_snk_in_3_cycle : ENTITY dp_lib.dp_pipeline
GENERIC MAP (
g_pipeline => 3 -- 0 for wires, > 0 for registers,
)
PORT MAP (
rst => dp_rst,
clk => dp_clk,
snk_in => st_histogram_snk_in,
src_out => st_histogram_snk_in_ppp
); );
u_dp_pipeline_st_histogram_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 => st_histogram_snk_in,
src_out => st_histogram_snk_in_pppp
);
---------------------------------------
-- create address from the source data
check_adr <= TO_UINT( st_histogram_snk_in_ppp.data(g_data_w-1 DOWNTO c_adr_low) );
-- dbg_check_adr <= st_histogram_snk_in_ppp.data(g_data_w -1 DOWNTO c_adr_low);
p_prev_check_adr : PROCESS (dp_rst, dp_clk, check_adr)
BEGIN
IF dp_rst='1' THEN
prev_check_adr <= 0;
ELSIF rising_edge(dp_clk) THEN
prev_check_adr <= check_adr;
END IF;
END PROCESS;
-----------------------------
-- when valid increase array based on address
nxt_check_arr_cnt <= data_check_arr(check_adr) + 1 WHEN st_histogram_snk_in_ppp.valid = '1' ELSE data_check_arr(check_adr);
--------------------
-- filling the array
p_cumulate_testdata : PROCESS (dp_rst, dp_clk, nxt_check_arr_cnt, check_adr, st_histogram_snk_in_ppp.sync) --misses prev_check_adr
BEGIN
--PROCESS
--c_data_check_arr(check_adr) <= nxt_check_arr_cnt;
IF dp_rst='1' THEN
data_check_arr(0 TO g_nof_bins) <= (OTHERS => 0);
ELSIF rising_edge(dp_clk) THEN
--data_check_arr(prev_check_adr) <= nxt_check_arr_cnt;
data_check_arr(check_adr) <= nxt_check_arr_cnt; --old timing
IF st_histogram_snk_in_ppp.sync='1' THEN
data_check_arr(0 TO g_nof_bins) <= (check_adr => 1, OTHERS => 0 ); -- null except check_adr
--
END IF;
END IF;
END PROCESS;
---------------------
-- extra dbg signals
dbg_int_data_miso <= TO_UINT(st_histogram_dbg_ram_miso.rddata);
dbg_int_data_arr <= data_check_arr(prev_check_adr);
---------------------
-- selftest
-- p_selfcheck : PROCESS (dp_rst, dp_clk, data_check_arr, prev_check_adr, st_histogram_dbg_ram_miso.rddata)
-- BEGIN
-- --PROCESS
-- -- compare cumulated testdata with ram_mosi
--
-- --dbg_int_data_miso <= TO_UINT(st_histogram_dbg_ram_miso.rddata);
-- --dbg_int_data_arr <= data_check_arr(check_adr);
-- IF rising_edge(dp_clk) THEN
-- --dbg_error_location <= '0';
-- --dbg_int_data_miso <= TO_UINT(st_histogram_dbg_ram_miso.rddata);
-- --dbg_int_data_arr <= data_check_arr(check_adr);
-- IF data_check_arr(prev_check_adr) /= TO_UINT(st_histogram_dbg_ram_miso.rddata) AND st_histogram_snk_in_pppp.valid='1' THEN
-- dbg_error_location <= '1';
-- REPORT "The value written to the RAM is not what it should be. See signal 'dbg_int_data_arr'. The failure concerns the bin (and array) address: " &integer'image(prev_check_adr) SEVERITY ERROR;
-- error_cnt <= error_cnt + 1;
-- ELSE
-- dbg_error_location <= '0';
-- END IF;
-- END IF;
--
---- IF dp_rst='1' THEN
---- data_check_arr(0 TO g_nof_bins) <= (OTHERS => 0);
---- ELSIF rising_edge(dp_clk) THEN
---- data_check_arr(check_adr) <= nxt_check_arr_cnt;
---- END IF;
-- END PROCESS;
-- show the location of an error after a small delay (to prevent spikes) when the data written is not the same as the reference and only when the data was initially valid. Do not allow to be triggered at the testbench end.
dbg_error_location <= '1' AFTER c_dp_clk_period/5 WHEN ( (data_check_arr(prev_check_adr) /= TO_UINT(st_histogram_dbg_ram_miso.rddata) ) AND st_histogram_snk_in_pppp.valid='1' AND tb_end='0' ) ELSE '0';
ASSERT dbg_error_location='0' REPORT "The value written to the RAM is not what it should be. Comparison failed on (bin and array) address: " &integer'image(prev_check_adr) SEVERITY ERROR;
--error count
p_count_total_error_cnt : PROCESS (dp_clk, dbg_error_location)
BEGIN
IF dp_rst='1' THEN
error_cnt <= 0;
ELSIF dbg_error_location='1' AND tb_end='0' AND rising_edge(dp_clk) THEN
error_cnt <= error_cnt + 1;
END IF;
END PROCESS;
p_view_total_error_cnt : PROCESS (tb_end, error_cnt)
BEGIN
IF tb_end='1' AND error_cnt>0 THEN
REPORT "When comparing there were " &integer'image(error_cnt) &" cycles where the value in the RAM address was not the value expected" SEVERITY ERROR;
END IF;
END PROCESS;
END tb; END tb;
-------------------------------------------------------------------------------
--
-- 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:
-- Description:
-- .
LIBRARY IEEE;
USE IEEE.std_logic_1164.ALL;
ENTITY tb_tb_st_histogram IS
END tb_tb_st_histogram;
ARCHITECTURE tb OF tb_tb_st_histogram IS
SIGNAL tb_end : STD_LOGIC := '0'; -- declare tb_end to avoid 'No objects found' error on 'when -label tb_end'
BEGIN
-- Usage
-- > as 8
-- > run -all
-- > Testbenches are self-checking
--
-- g_sync_length : NATURAL := 200;
-- g_nof_sync : NATURAL := 3;
-- g_data_w : NATURAL := 4;
-- g_nof_bins : NATURAL := 8;
-- g_nof_data : NATURAL := 200;
-- --g_str : STRING := "freq.density";
-- g_valid_gap : STRING := "custom"; -- "false" or "true" or "custom"
-- g_snk_in_data_sim_type : STRING := "same rw" -- "counter" or "toggle" or "same rw" or "mix"
--
-- do test for different number of bins
u_tb_st_histogram_counter_nof_2 : ENTITY work.tb_st_histogram GENERIC MAP (200, 3, 1, 2, 200, "true" , "counter" );
u_tb_st_histogram_counter_nof_4 : ENTITY work.tb_st_histogram GENERIC MAP (200, 3, 2, 4, 200, "true" , "counter" );
u_tb_st_histogram_counter : ENTITY work.tb_st_histogram GENERIC MAP (200, 3, 4, 8, 200, "true" , "counter" );
-- do tests for RAM delay issues
u_tb_st_histogram_toggle : ENTITY work.tb_st_histogram GENERIC MAP (200, 3, 4, 8, 200, "true" , "toggle" );
u_tb_st_histogram_same_rw : ENTITY work.tb_st_histogram GENERIC MAP (200, 3, 4, 8, 200, "custom", "same rw" );
END tb;
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment