Skip to content
Snippets Groups Projects
Commit e1a38ce4 authored by Jan Oudman's avatar Jan Oudman
Browse files

Added a restructured version of st_histogram

parent c422653f
Branches
No related tags found
2 merge requests!28Master,!20Resolve STAT-314
......@@ -13,6 +13,7 @@ synth_files =
src/vhdl/st_histogram.vhd
src/vhdl/st_histogram_reg.vhd
src/vhdl/mms_st_histogram.vhd
src/vhdl/st_histogram_8_april.vhd
test_bench_files =
tb/vhdl/tb_st_acc.vhd
......
......@@ -23,7 +23,29 @@
-- Author: J.W.E. Oudman
-- Purpose: Create a histogram from the input data and present it to the MM bus
-- Description:
--
-- mms_st_histogram couples the st_histogram component which works entirely
-- in the dp clock domain through st_histogram_reg that handles the cross
-- domain conversion to the MM bus.
--
--
-- --------------------------------------
-- | mms_st_histogram |
-- | |
-- | ---------------- | -------
-- snk_in -->|-->| st_histogram | | ^
-- | ---------------- | |
-- | | ^ |
-- | | | | dp clock domain
-- | ram_st_histogram_miso |
-- | | | |
-- | | ram_st_histogram_mosi | |
-- | v | | v
-- | -------------------- | -------
-- | | st_histogram_reg |-- ram_miso -->|--> mm clock domain
-- | | |<-- ram_mosi --|<--
-- | -------------------- | -------
-- | |
-- --------------------------------------
--
--
-------------------------------------------------------------------------------
......
......@@ -79,7 +79,7 @@ USE technology_lib.technology_select_pkg.ALL;
ENTITY st_histogram IS
GENERIC (
g_in_data_w : NATURAL := 14; -- >= 9 when g_nof_bins is 512; (max. c_dp_stream_data_w =768)
g_in_data_w : NATURAL := 14; -- >= 9 when g_nof_bins is 512; (max. c_dp_stream_data_w =768) <-- maybe just g_data_w ??
g_nof_bins : NATURAL := 512; -- is a power of 2 and g_nof_bins <= c_data_span; max. 512
g_nof_data : NATURAL; --
g_str : STRING := "freq.density" -- to select output to MM bus ("frequency" or "freq.density")
......@@ -100,7 +100,7 @@ ENTITY st_histogram IS
END st_histogram;
ARCHITECTURE str OF st_histogram IS
ARCHITECTURE rtl OF st_histogram IS
CONSTANT c_data_span : NATURAL := pow2(g_in_data_w); -- any use?
CONSTANT c_bin_w : NATURAL := ceil_log2(g_nof_data); -- any use?
......@@ -118,9 +118,9 @@ ARCHITECTURE str OF st_histogram IS
SIGNAL dp_pipeline_src_out_p : t_dp_sosi;
SIGNAL dp_pipeline_src_out_pp : t_dp_sosi;
SIGNAL adr_b_cnt : NATURAL := 1;
SIGNAL nxt_adr_b_cnt : NATURAL;
SIGNAL prev_adr_b : STD_LOGIC_VECTOR(g_in_data_w -1 DOWNTO c_adr_low);
SIGNAL rd_adr_cnt : NATURAL := 1;
SIGNAL nxt_rd_adr_cnt : NATURAL;
SIGNAL prev_rd_adr : STD_LOGIC_VECTOR(g_in_data_w -1 DOWNTO c_adr_low);
-- Toggle implementation signals
SIGNAL prev_same_r_w_adr : STD_LOGIC := '0';
......@@ -131,38 +131,38 @@ ARCHITECTURE str OF st_histogram IS
SIGNAL ram_pointer : STD_LOGIC := '0';
SIGNAL cycle_cnt : NATURAL := 0 ;
SIGNAL nxt_cycle_cnt : NATURAL := 0 ;
SIGNAL wr_en_a : STD_LOGIC := '0';
SIGNAL nxt_wr_en_a : STD_LOGIC;
SIGNAL wr_dat_a : STD_LOGIC_VECTOR(c_word_w -1 DOWNTO 0);
SIGNAL nxt_wr_dat_a : STD_LOGIC_VECTOR(c_word_w -1 DOWNTO 0);
SIGNAL adr_a : STD_LOGIC_VECTOR(g_in_data_w -1 DOWNTO c_adr_low);
SIGNAL adr_b : STD_LOGIC_VECTOR(g_in_data_w -1 DOWNTO c_adr_low);
SIGNAL rd_en_b : STD_LOGIC := '0';
SIGNAL rd_dat_b : STD_LOGIC_VECTOR(c_word_w -1 DOWNTO 0);
SIGNAL rd_val_b : STD_LOGIC;
SIGNAL wr_en : STD_LOGIC := '0';
SIGNAL nxt_wr_en : STD_LOGIC;
SIGNAL wr_dat : STD_LOGIC_VECTOR(c_word_w -1 DOWNTO 0);
SIGNAL nxt_wr_dat : STD_LOGIC_VECTOR(c_word_w -1 DOWNTO 0);
SIGNAL wr_adr : STD_LOGIC_VECTOR(g_in_data_w -1 DOWNTO c_adr_low);
SIGNAL rd_adr : STD_LOGIC_VECTOR(g_in_data_w -1 DOWNTO c_adr_low);
SIGNAL rd_en : STD_LOGIC := '0';
SIGNAL rd_dat : STD_LOGIC_VECTOR(c_word_w -1 DOWNTO 0);
SIGNAL rd_val : STD_LOGIC;
SIGNAL mm_adr_cnt : NATURAL := 0 ;
SIGNAL mm_adr_illegal : STD_LOGIC := '0';
SIGNAL mm_adr_illegal_pp : STD_LOGIC := '0';
SIGNAL ram_0_wr_en_a : STD_LOGIC;
SIGNAL ram_0_wr_en_b : STD_LOGIC := '0'; -- pointer=1, temp'0'
SIGNAL ram_0_wr_dat_a : 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_adr_a : STD_LOGIC_VECTOR(g_in_data_w -1 DOWNTO c_adr_low);
SIGNAL ram_0_adr_b : STD_LOGIC_VECTOR(g_in_data_w -1 DOWNTO c_adr_low);
SIGNAL ram_0_rd_en_b : STD_LOGIC;
SIGNAL ram_0_rd_dat_b : STD_LOGIC_VECTOR(c_word_w -1 DOWNTO 0);
SIGNAL ram_0_rd_val_b : STD_LOGIC;
SIGNAL ram_1_wr_en_a : STD_LOGIC;
SIGNAL ram_1_wr_dat_a : STD_LOGIC_VECTOR(c_word_w -1 DOWNTO 0);
SIGNAL ram_1_adr_a : STD_LOGIC_VECTOR(g_in_data_w -1 DOWNTO c_adr_low);
SIGNAL ram_1_adr_b : STD_LOGIC_VECTOR(g_in_data_w -1 DOWNTO c_adr_low);
SIGNAL ram_1_rd_en_b : STD_LOGIC;
SIGNAL ram_1_rd_dat_b : STD_LOGIC_VECTOR(c_word_w -1 DOWNTO 0);
SIGNAL ram_1_rd_val_b : 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_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_rd_adr : STD_LOGIC_VECTOR(g_in_data_w -1 DOWNTO c_adr_low);
SIGNAL ram_0_rd_en : STD_LOGIC;
SIGNAL ram_0_rd_dat : STD_LOGIC_VECTOR(c_word_w -1 DOWNTO 0);
SIGNAL ram_0_rd_val : STD_LOGIC;
SIGNAL ram_1_wr_en : STD_LOGIC;
SIGNAL ram_1_wr_dat : STD_LOGIC_VECTOR(c_word_w -1 DOWNTO 0);
SIGNAL ram_1_wr_adr : STD_LOGIC_VECTOR(g_in_data_w -1 DOWNTO c_adr_low);
SIGNAL ram_1_rd_adr : STD_LOGIC_VECTOR(g_in_data_w -1 DOWNTO c_adr_low);
SIGNAL ram_1_rd_en : STD_LOGIC;
SIGNAL ram_1_rd_dat : STD_LOGIC_VECTOR(c_word_w -1 DOWNTO 0);
SIGNAL ram_1_rd_val : STD_LOGIC;
SIGNAL ram_out_wr_en : STD_LOGIC;
SIGNAL ram_out_wr_dat : STD_LOGIC_VECTOR(c_word_w -1 DOWNTO 0);
......@@ -175,14 +175,6 @@ ARCHITECTURE str OF st_histogram IS
SIGNAL prev_ram_out_wr_adr : STD_LOGIC_VECTOR(g_in_data_w -1 DOWNTO c_adr_low);
SIGNAL ram_out_same_w_r_adr : STD_LOGIC;
-- SIGNAL fifo_in_wr_en : STD_LOGIC := '0';
-- SIGNAL fifo_in_wr_dat : STD_LOGIC_VECTOR(c_word_w -1 DOWNTO 0) := (OTHERS => '0');
-- SIGNAL fifo_in_wr_adr : STD_LOGIC_VECTOR(g_in_data_w -1 DOWNTO c_adr_low) := (OTHERS => '0');
-- SIGNAL fifo_in_rd_adr : STD_LOGIC_VECTOR(g_in_data_w -1 DOWNTO c_adr_low) := (OTHERS => '0');
-- SIGNAL fifo_in_rd_en : STD_LOGIC := '0';
-- SIGNAL fifo_in_rd_dat : STD_LOGIC_VECTOR(c_word_w -1 DOWNTO 0);
-- SIGNAL fifo_in_rd_val : STD_LOGIC;
BEGIN
-----------------------------------------------------------------------------
......@@ -198,9 +190,9 @@ BEGIN
-- . it is the same as 2 cycles back but not the last copy the data to be
-- written directly into the counter instead of trying to read (ask) it
-- back from RAM at the same clock cycle (which is impossible)
-- . it is not the same enable the nxt_wr_dat_a data to be written
-- at the next cycle by making nxt_wr_en_a high
-- . Write the wr_dat_a data to the RAM
-- . it is not the same enable the nxt_wr_dat data to be written
-- at the next cycle by making nxt_wr_en high
-- . Write the wr_dat data to the RAM
-- . At the snk_in.sync pulse:
-- . let first 2 cycles start counting from 0 again
-- . (plus 2 cycles) let counting depend on values in RAM (which should
......@@ -210,299 +202,247 @@ BEGIN
-- . restart from 0 when adress is not the same as previous adress
-- . 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;
----------------------------------------------------------------------------
p_bin_cnt_switch : PROCESS(snk_in) IS
-- cycles after sync
u_dp_pipeline_snk_in_1_cycle : ENTITY dp_lib.dp_pipeline
GENERIC MAP (
g_pipeline => 1 -- 0 for wires, > 0 for registers,
)
PORT MAP (
rst => dp_rst,
clk => dp_clk,
snk_in => snk_in,
src_out => dp_pipeline_src_out_p
);
p_bin_cnt_switch : PROCESS(snk_in) IS -- misses g_nof_bins ??
BEGIN
adr_b <= (OTHERS =>'0');
rd_adr <= (OTHERS =>'0');
IF g_nof_bins>1 THEN
adr_b <= snk_in.data(g_in_data_w-1 DOWNTO c_adr_low);-- WHEN snk_in.valid='1' ELSE (OTHERS =>'0'); -- AND dp_rst='0';
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';
END IF;
END PROCESS;
-- Alternative method:
-- adr_b <= snk_in.data(g_in_data_w-1 DOWNTO c_adr_low) WHEN g_nof_bins >1 ELSE (OTHERS =>'0');
p_rd_en_b : PROCESS(dp_pipeline_src_out_p.sync, snk_in.valid, wr_en_a, adr_a, adr_b, prev_adr_b) IS
BEGIN
rd_en_b <= '1';
IF dp_pipeline_src_out_p.sync = '1' AND wr_en_a = '1' THEN --
rd_en_b <= '0';
ELSIF adr_a = adr_b AND adr_a /= prev_adr_b THEN -- toggle implementation
rd_en_b <= '0'; -- toggle implementation
ELSIF snk_in.valid = '0' AND wr_en_a = '1' THEN
rd_en_b <= '1';
END IF;
END PROCESS;
-- Pipelined to compare previous rd_adr against current
u_common_pipeline_adr_cnt : ENTITY common_lib.common_pipeline --rename to u_common_pipeline_rd_adr
GENERIC MAP (
g_representation => "UNSIGNED", --orig. signed
g_pipeline => 1,
g_in_dat_w => c_adr_w,
g_out_dat_w => c_adr_w
)
PORT MAP (
clk => dp_clk,
clken => '1',
in_dat => STD_LOGIC_VECTOR(rd_adr),
out_dat => prev_rd_adr
);
-- Alternative method:
-- rd_en_b <= '0' WHEN (dp_pipeline_src_out_p.sync = '1' AND wr_en_a = '1')
-- OR (adr_a = adr_b AND adr_a /= prev_adr_b) ELSE '1';
p_nxt_wr_dat : PROCESS(rd_dat_b, adr_b_cnt, rd_val_b, dp_pipeline_src_out_p.sync, dp_pipeline_src_out_pp.sync, wr_en_a) IS
p_nxt_wr_en : PROCESS(prev_rd_adr, rd_adr, snk_in.sync) IS -- misses g_nof_bins ??
BEGIN
nxt_wr_dat_a <= (OTHERS => '0');
IF dp_pipeline_src_out_p.sync = '1' THEN
nxt_wr_dat_a <= TO_UVEC(adr_b_cnt, c_word_w);
ELSIF dp_pipeline_src_out_pp.sync = '1' THEN
nxt_wr_dat_a <= TO_UVEC(adr_b_cnt, c_word_w);
ELSIF same_r_w_adr = '1' AND rd_val_b = '0' THEN -- toggle implementation: same adress forced rd_val to 0, counter instead of ram knows what to write
nxt_wr_dat_a <= TO_UVEC(adr_b_cnt, c_word_w); -- toggle implementation
ELSIF dp_pipeline_src_out_pp.valid = '0' AND prev_same_r_w_adr = '1' THEN -- toggle implementation: prevent 2* rd_dat_b
nxt_wr_dat_a <= TO_UVEC(adr_b_cnt, c_word_w); -- toggle implementation
ELSIF rd_val_b = '1' THEN
nxt_wr_dat_a <= INCR_UVEC(rd_dat_b, adr_b_cnt);
nxt_wr_en <= '0';
IF rd_adr /= prev_rd_adr THEN
nxt_wr_en <= '1';
ELSIF snk_in.sync = '1' AND g_nof_bins = 1 THEN
nxt_wr_en <= '1';
ELSIF snk_in.sync = '1' THEN
nxt_wr_en <= '1';
END IF;
END PROCESS;
-- Alternative method:
-- nxt_wr_dat_a <= TO_UVEC(adr_b_cnt, c_word_w) WHEN dfgdfg OR
--
--
-- ELSE INCR_UVEC(rd_dat_b, adr_b_cnt) WHEN rd_val_b = '1' ELSE (others => 0)
-- requested data on adress can be written back 2 cycles later
u_common_pipeline_adr : ENTITY common_lib.common_pipeline
GENERIC MAP (
g_representation => "UNSIGNED", --orig. signed
g_pipeline => 2,
g_in_dat_w => c_adr_w,
g_out_dat_w => c_adr_w
)
PORT MAP (
clk => dp_clk,
clken => '1',
in_dat => STD_LOGIC_VECTOR(rd_adr),
out_dat => wr_adr
);
p_nxt_wr_en : PROCESS(prev_adr_b, adr_b, snk_in.sync) IS
p_rd_en : PROCESS(dp_pipeline_src_out_p.sync, snk_in.valid, wr_en, wr_adr, rd_adr, prev_rd_adr) IS
BEGIN
nxt_wr_en_a <= '0';
IF adr_b /= prev_adr_b THEN
nxt_wr_en_a <= '1';
ELSIF snk_in.sync = '1' AND g_nof_bins = 1 THEN
nxt_wr_en_a <= '1';
ELSIF snk_in.sync = '1' THEN
nxt_wr_en_a <= '1';
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;
p_prev_adr_cnt : PROCESS(adr_a, adr_b, prev_adr_b, adr_b_cnt, snk_in.sync, snk_in.valid, dp_pipeline_src_out_p.valid, dp_pipeline_src_out_p.sync) IS
-- cycles after sync
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 => dp_pipeline_src_out_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;
BEGIN
nxt_adr_b_cnt <= 1;
IF adr_b = prev_adr_b AND snk_in.valid = '1' AND snk_in.sync = '0' THEN
nxt_adr_b_cnt <= adr_b_cnt + 1 ;
ELSIF snk_in.valid = '0' AND snk_in.sync = '1' THEN --address doesn't matter at unvalid and sync, removed: adr_b = prev_adr_b AND
nxt_adr_b_cnt <= 0;
ELSIF adr_b = prev_adr_b AND snk_in.valid = '0' THEN
nxt_adr_b_cnt <= adr_b_cnt;
ELSIF adr_b = prev_adr_b 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_adr_b_cnt <= 1; -- toggle implementation
ELSIF adr_b = prev_adr_b AND snk_in.valid = '1' AND dp_pipeline_src_out_p.valid = '0' THEN -- toggle implementation
nxt_adr_b_cnt <= adr_b_cnt + 1; -- toggle implementation
ELSIF adr_a = adr_b AND snk_in.valid = '1' AND snk_in.sync = '1' THEN -- toggle implementation; do the adresses even matter?
nxt_adr_b_cnt <= 1; -- toggle implementation
ELSIF adr_a = adr_b AND adr_b /= prev_adr_b AND snk_in.valid = '0' THEN -- toggle implementation: disable count; -2 cycles count + 0
nxt_adr_b_cnt <= TO_UINT(wr_dat_a); -- toggle implementation
ELSIF adr_a = adr_b AND snk_in.valid = '1' AND dp_pipeline_src_out_p.sync = '0' THEN -- toggle implentation
nxt_adr_b_cnt <= TO_UINT(wr_dat_a) + 1; -- toggle implentation
ELSIF adr_a = adr_b AND snk_in.valid = '0' THEN -- toggle implentation
nxt_adr_b_cnt <= adr_b_cnt; -- toggle implentation
ELSIF snk_in.valid = '0' AND adr_b /= prev_adr_b AND adr_a /= adr_b THEN
nxt_adr_b_cnt <= 0;
nxt_rd_adr_cnt <= 1;
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(adr_a, adr_b) IS -- toggle implentation
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 adr_a = adr_b AND g_nof_bins > 1 THEN
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
u_common_pipeline_sl_same_r_w_adr : ENTITY common_lib.common_pipeline_sl
GENERIC MAP(
g_pipeline => 1 -- 0 for wires, > 0 for registers,
)
PORT MAP (
clk => dp_clk,
in_dat => same_r_w_adr,
out_dat => prev_same_r_w_adr
);
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;
BEGIN
nxt_wr_dat <= (OTHERS => '0');
IF dp_pipeline_src_out_p.sync = '1' THEN
nxt_wr_dat <= TO_UVEC(rd_adr_cnt, c_word_w);
ELSIF dp_pipeline_src_out_pp.sync = '1' THEN
nxt_wr_dat <= TO_UVEC(rd_adr_cnt, c_word_w);
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
nxt_wr_dat <= TO_UVEC(rd_adr_cnt, c_word_w); -- toggle implementation
ELSIF dp_pipeline_src_out_pp.valid = '0' AND prev_same_r_w_adr = '1' THEN -- toggle implementation: prevent 2* rd_dat
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 PROCESS;
p_clk : PROCESS(dp_clk, dp_rst)
BEGIN
IF dp_rst='1' THEN
adr_b_cnt <= 0;
wr_en_a <= '0';
rd_adr_cnt <= 0;
wr_en <= '0';
ELSIF rising_edge(dp_clk) THEN
adr_b_cnt <= nxt_adr_b_cnt;
wr_dat_a <= nxt_wr_dat_a;
wr_en_a <= nxt_wr_en_a;
rd_adr_cnt <= nxt_rd_adr_cnt;
wr_dat <= nxt_wr_dat;
wr_en <= nxt_wr_en;
same_r_w_adr <= nxt_same_r_w_adr;
cycle_cnt <= nxt_cycle_cnt;
prev_ram_out_wr_adr <= ram_out_wr_adr;
cycle_cnt <= nxt_cycle_cnt; -- ( ander functieblok )
prev_ram_out_wr_adr <= ram_out_wr_adr; -- ''
END IF;
END PROCESS;
-----------------------------------------------------------------------------
-- RAM selector
-- RAM selector & Dual swapped RAM instances:
-- 2 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
--
-- Depending on ram_pointer:
-- ram_pointer = '0': input RAM_0, output RAM_1
-- ram_pointer = '1': input RAM_1, output RAM_0
--
-- input in: dp_pipeline_src_out_pp.sync; wr_en; wr_dat; wr_adr;
-- rd_adr; rd_en;
-- out: rd_dat, rd_val
--
-- output in: ram_out_wr_en; ram_out_wr_dat; ram_out_wr_adr; ram_out_rd_adr;
-- ram_out_rd_en
-- out: ram_out_rd_dat; ram_out_rd_val
-----------------------------------------------------------------------------
p_ram_pointer_at_sync : PROCESS(dp_pipeline_src_out_pp) IS
p_ram_pointer_at_sync : PROCESS(dp_pipeline_src_out_pp) IS -- needs nxt_ram_pointer ??
BEGIN
IF dp_pipeline_src_out_pp.sync = '1' THEN
ram_pointer <= NOT(ram_pointer);
END IF;
END PROCESS;
p_ram_pointer : PROCESS(ram_pointer, wr_en_a, wr_dat_a, adr_a, adr_b, rd_en_b, ram_0_rd_dat_b, ram_0_rd_val_b,
ram_out_wr_en, ram_out_wr_dat, ram_out_wr_adr, ram_out_rd_adr, ram_out_rd_en, ram_1_rd_dat_b, ram_1_rd_val_b) IS
p_ram_pointer : PROCESS(ram_pointer, wr_en, wr_dat, wr_adr, rd_adr, rd_en, ram_0_rd_dat, ram_0_rd_val,
ram_out_wr_en, ram_out_wr_dat, ram_out_wr_adr, ram_out_rd_adr, ram_out_rd_en, ram_1_rd_dat, ram_1_rd_val) IS
BEGIN
IF ram_pointer='0' THEN
-- ST side (RAM 0)
ram_0_wr_en_a <= wr_en_a;
ram_0_wr_dat_a <= wr_dat_a;
ram_0_adr_a <= adr_a;
ram_0_adr_b <= adr_b;
ram_0_rd_en_b <= rd_en_b;
rd_dat_b <= ram_0_rd_dat_b;
rd_val_b <= ram_0_rd_val_b;
ram_0_wr_en <= wr_en;
ram_0_wr_dat <= wr_dat;
ram_0_wr_adr <= wr_adr;
ram_0_rd_adr <= rd_adr;
ram_0_rd_en <= rd_en;
rd_dat <= ram_0_rd_dat;
rd_val <= ram_0_rd_val;
-- dp_clk'd MM side (RAM 1)
ram_1_wr_en_a <= ram_out_wr_en;
ram_1_wr_dat_a <= ram_out_wr_dat;
ram_1_adr_a <= ram_out_wr_adr;
ram_1_adr_b <= ram_out_rd_adr;
ram_1_rd_en_b <= ram_out_rd_en;
ram_out_rd_dat <= ram_1_rd_dat_b;
ram_out_rd_val <= ram_1_rd_val_b;
ram_1_wr_en <= ram_out_wr_en;
ram_1_wr_dat <= ram_out_wr_dat;
ram_1_wr_adr <= ram_out_wr_adr;
ram_1_rd_adr <= ram_out_rd_adr;
ram_1_rd_en <= ram_out_rd_en;
ram_out_rd_dat <= ram_1_rd_dat;
ram_out_rd_val <= ram_1_rd_val;
ELSE -- ram_pointer='1'
-- ST side (RAM 1)
ram_1_wr_en_a <= wr_en_a;
ram_1_wr_dat_a <= wr_dat_a;
ram_1_adr_a <= adr_a;
ram_1_adr_b <= adr_b;
ram_1_rd_en_b <= rd_en_b;
rd_dat_b <= ram_1_rd_dat_b;
rd_val_b <= ram_1_rd_val_b;
ram_1_wr_en <= wr_en;
ram_1_wr_dat <= wr_dat;
ram_1_wr_adr <= wr_adr;
ram_1_rd_adr <= rd_adr;
ram_1_rd_en <= rd_en;
rd_dat <= ram_1_rd_dat;
rd_val <= ram_1_rd_val;
--dp_clk'd MM side (RAM 0)
ram_0_wr_en_a <= ram_out_wr_en;
ram_0_wr_dat_a <= ram_out_wr_dat;
ram_0_adr_a <= ram_out_wr_adr;
ram_0_adr_b <= ram_out_rd_adr;
ram_0_rd_en_b <= ram_out_rd_en;
ram_out_rd_dat <= ram_0_rd_dat_b;
ram_out_rd_val <= ram_0_rd_val_b;
ram_0_wr_en <= ram_out_wr_en;
ram_0_wr_dat <= ram_out_wr_dat;
ram_0_wr_adr <= ram_out_wr_adr;
ram_0_rd_adr <= ram_out_rd_adr;
ram_0_rd_en <= ram_out_rd_en;
ram_out_rd_dat <= ram_0_rd_dat;
ram_out_rd_val <= ram_0_rd_val;
END IF;
END PROCESS;
-----------------------------------------------------------------------------
-- Pipeline for adress
-----------------------------------------------------------------------------
u_common_pipeline_adr : ENTITY common_lib.common_pipeline
GENERIC MAP (
g_representation => "UNSIGNED", --orig. signed
g_pipeline => 2,
g_in_dat_w => c_adr_w,
g_out_dat_w => c_adr_w
)
PORT MAP (
clk => dp_clk,
clken => '1',
in_dat => STD_LOGIC_VECTOR(adr_b),
out_dat => adr_a
);
-----------------------------------------------------------------------------
-- Pipeline for toggle issue
-----------------------------------------------------------------------------
u_common_pipeline_sl_same_r_w_adr : ENTITY common_lib.common_pipeline_sl
GENERIC MAP(
g_pipeline => 1 -- 0 for wires, > 0 for registers,
)
PORT MAP (
clk => dp_clk,
in_dat => same_r_w_adr,
out_dat => prev_same_r_w_adr
);
-----------------------------------------------------------------------------
-- Pipeline for adresscounter
-----------------------------------------------------------------------------
u_common_pipeline_adr_cnt : ENTITY common_lib.common_pipeline
GENERIC MAP (
g_representation => "UNSIGNED", --orig. signed
g_pipeline => 1,
g_in_dat_w => c_adr_w,
g_out_dat_w => c_adr_w
)
PORT MAP (
clk => dp_clk,
clken => '1',
in_dat => STD_LOGIC_VECTOR(adr_b),
out_dat => prev_adr_b
);
-----------------------------------------------------------------------------
-- Pipeline for cycles after sync
-----------------------------------------------------------------------------
u_dp_pipeline_snk_in_1_cycle : ENTITY dp_lib.dp_pipeline
GENERIC MAP (
g_pipeline => 1 -- 0 for wires, > 0 for registers,
)
PORT MAP (
rst => dp_rst,
clk => dp_clk,
snk_in => snk_in,
src_out => dp_pipeline_src_out_p
);
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 => dp_pipeline_src_out_pp
);
-----------------------------------------------------------------------------
-- Pipeline for identified illegal read requests after new sync
-----------------------------------------------------------------------------
u_common_pipeline_sl_mm_adr_illegal : ENTITY common_lib.common_pipeline_sl
GENERIC MAP(
g_pipeline => 2 -- 0 for wires, > 0 for registers,
)
PORT MAP (
clk => dp_clk,
in_dat => mm_adr_illegal,
out_dat => mm_adr_illegal_pp
);
-----------------------------------------------------------------------------
-- Dual swapped RAM instance
-----------------------------------------------------------------------------
-- Dual swapped RAM instances
ram_0: ENTITY common_lib.common_ram_r_w
GENERIC MAP (
g_technology => c_tech_select_default,
......@@ -513,13 +453,13 @@ BEGIN
rst => dp_rst,
clk => dp_clk,
clken => '1', -- only necessary for Stratix iv
wr_en => ram_0_wr_en_a,
wr_adr => ram_0_adr_a,
wr_dat => ram_0_wr_dat_a,
rd_en => ram_0_rd_en_b,
rd_adr => ram_0_adr_b,
rd_dat => ram_0_rd_dat_b,
rd_val => ram_0_rd_val_b
wr_en => ram_0_wr_en,
wr_adr => ram_0_wr_adr,
wr_dat => ram_0_wr_dat,
rd_en => ram_0_rd_en,
rd_adr => ram_0_rd_adr,
rd_dat => ram_0_rd_dat,
rd_val => ram_0_rd_val
);
ram_1: ENTITY common_lib.common_ram_r_w
......@@ -532,25 +472,43 @@ BEGIN
rst => dp_rst,
clk => dp_clk,
clken => '1', -- only necessary for Stratix iv
wr_en => ram_1_wr_en_a,
wr_adr => ram_1_adr_a,
wr_dat => ram_1_wr_dat_a,
rd_en => ram_1_rd_en_b,
rd_adr => ram_1_adr_b,
rd_dat => ram_1_rd_dat_b,
rd_val => ram_1_rd_val_b
wr_en => ram_1_wr_en,
wr_adr => ram_1_wr_adr,
wr_dat => ram_1_wr_dat,
rd_en => ram_1_rd_en,
rd_adr => ram_1_rd_adr,
rd_dat => ram_1_rd_dat,
rd_val => ram_1_rd_val
);
-----------------------------------------------------------------------------
-- Connect interface to DUAL swapped RAM, read out histogram statistics:
-- . Limit the data read by the MM master to the RAM block where it started
-- to read (the values read after a new sync will be OTHERS => '0')
-- . In the last g_nof_bins cycles all addresses will sequentially be cleared
--
-- RAM selector:
-- input: ram_out_rd_dat; ram_out_rd_val
-- output: ram_out_wr_en; ram_out_wr_dat; ram_out_wr_adr; ram_out_rd_adr;
-- ram_out_wr_en
-- (PORT):
-- input: snk_in; sla_in_ram_mosi
-- output: sla_out_ram_miso
-----------------------------------------------------------------------------
-- Pipeline for identified illegal read requests after new sync
u_common_pipeline_sl_mm_adr_illegal : ENTITY common_lib.common_pipeline_sl
GENERIC MAP(
g_pipeline => 2 -- 0 for wires, > 0 for registers,
)
PORT MAP (
clk => dp_clk,
in_dat => mm_adr_illegal,
out_dat => mm_adr_illegal_pp
);
p_mm_adr_illegal : PROCESS(snk_in.sync, mm_adr_cnt) IS
BEGIN
IF snk_in.sync = '1' AND mm_adr_cnt /= 0 THEN
......@@ -561,11 +519,9 @@ BEGIN
END IF;
END PROCESS;
mm_adr_cnt <= TO_UINT(sla_in_ram_mosi.address(c_ram.adr_w-1 DOWNTO 0)) WHEN sla_in_ram_mosi.rd = '1';
ram_out_same_w_r_adr <= '1' WHEN ram_out_wr_adr = sla_in_ram_mosi.address(c_ram.adr_w-1 DOWNTO 0) ELSE '0';
p_ram_to_fifo : PROCESS(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
BEGIN
IF dp_pipeline_src_out_pp.sync = '1' THEN
......@@ -576,51 +532,39 @@ BEGIN
ram_out_wr_dat <= (OTHERS => '0');
ram_out_wr_en <= '1';
IF ram_out_same_w_r_adr = '1' THEN
--ram_out_rd_adr <= sla_in_ram_mosi.address(c_ram.adr_w-1 DOWNTO 0); -- fifo_in_rd_adr;
ram_out_rd_en <= '0'; --sla_in_ram_mosi.rd; -- fifo_in_rd_en;
sla_out_ram_miso.rddata(c_ram.dat_w-1 DOWNTO 0) <= (OTHERS => '0'); -- ram_out_rd_dat;
sla_out_ram_miso.rdval <= ram_out_rd_val; -- ram_out_rd_val;
ram_out_rd_en <= '0';
sla_out_ram_miso.rddata(c_ram.dat_w-1 DOWNTO 0) <= (OTHERS => '0');
sla_out_ram_miso.rdval <= ram_out_rd_val;
ELSE
ram_out_rd_adr <= sla_in_ram_mosi.address(c_ram.adr_w-1 DOWNTO 0); -- fifo_in_rd_adr;
ram_out_rd_en <= sla_in_ram_mosi.rd; -- fifo_in_rd_en;
ram_out_rd_adr <= sla_in_ram_mosi.address(c_ram.adr_w-1 DOWNTO 0);
ram_out_rd_en <= sla_in_ram_mosi.rd;
sla_out_ram_miso.rddata(c_ram.dat_w-1 DOWNTO 0) <= ram_out_rd_dat;
sla_out_ram_miso.rdval <= ram_out_rd_val; -- ram_out_rd_val;
sla_out_ram_miso.rdval <= ram_out_rd_val;
END IF;
--ram_out_rd_en <= '0';
nxt_cycle_cnt <= cycle_cnt +1;
ELSIF cycle_cnt > c_clear THEN
ram_out_wr_adr <= INCR_UVEC(prev_ram_out_wr_adr, 1);
--prev_ram_out_wr_adr <= ram_out_wr_adr;
nxt_cycle_cnt <= cycle_cnt +1;
IF ram_out_same_w_r_adr = '1' OR snk_in.sync = '1' THEN
--ram_out_rd_adr <= sla_in_ram_mosi.address(c_ram.adr_w-1 DOWNTO 0); -- fifo_in_rd_adr;
--ram_out_rd_en <= sla_in_ram_mosi.rd; -- fifo_in_rd_en;
sla_out_ram_miso.rddata(c_ram.dat_w-1 DOWNTO 0) <= (OTHERS => '0'); -- ram_out_rd_dat;
sla_out_ram_miso.rdval <= ram_out_rd_val; -- ram_out_rd_val;
sla_out_ram_miso.rddata(c_ram.dat_w-1 DOWNTO 0) <= (OTHERS => '0');
sla_out_ram_miso.rdval <= ram_out_rd_val;
ELSE
ram_out_rd_adr <= sla_in_ram_mosi.address(c_ram.adr_w-1 DOWNTO 0); -- fifo_in_rd_adr;
ram_out_rd_en <= sla_in_ram_mosi.rd; -- fifo_in_rd_en;
ram_out_rd_adr <= sla_in_ram_mosi.address(c_ram.adr_w-1 DOWNTO 0);
ram_out_rd_en <= sla_in_ram_mosi.rd;
sla_out_ram_miso.rddata(c_ram.dat_w-1 DOWNTO 0) <= ram_out_rd_dat;
sla_out_ram_miso.rdval <= ram_out_rd_val; -- ram_out_rd_val;
sla_out_ram_miso.rdval <= ram_out_rd_val;
END IF;
-- ELSIF snk_in.sync = '1' AND mm_adr_cnt /= 0 THEN
-- mm_adr_illegal <= '1';
-- ELSIF mm_adr_cnt = g_nof_bins THEN
-- mm_adr_illegal <= '0';
ELSIF mm_adr_illegal_pp = '1' THEN
ram_out_rd_adr <= sla_in_ram_mosi.address(c_ram.adr_w-1 DOWNTO 0); -- fifo_in_rd_adr;
ram_out_rd_en <= sla_in_ram_mosi.rd; -- fifo_in_rd_en;
sla_out_ram_miso.rddata(c_ram.dat_w-1 DOWNTO 0) <= (OTHERS => '0'); -- ram_out_rd_dat;
sla_out_ram_miso.rdval <= ram_out_rd_val; -- ram_out_rd_val;
ram_out_rd_adr <= sla_in_ram_mosi.address(c_ram.adr_w-1 DOWNTO 0);
ram_out_rd_en <= sla_in_ram_mosi.rd;
sla_out_ram_miso.rddata(c_ram.dat_w-1 DOWNTO 0) <= (OTHERS => '0');
sla_out_ram_miso.rdval <= ram_out_rd_val;
nxt_cycle_cnt <= cycle_cnt +1;
ELSE
-- ram_out_wr_en <= ram_mosi.wr --fifo_in_wr_en;
-- ram_out_wr_dat <= ram_mosi.wrdata(c_ram.dat_w-1 DOWNTO 0) -- fifo_in_wr_dat;
-- ram_out_wr_adr <= fifo_in_wr_adr;
ram_out_rd_adr <= sla_in_ram_mosi.address(c_ram.adr_w-1 DOWNTO 0); -- fifo_in_rd_adr;
ram_out_rd_en <= sla_in_ram_mosi.rd; -- fifo_in_rd_en;
sla_out_ram_miso.rddata(c_ram.dat_w-1 DOWNTO 0) <= ram_out_rd_dat; -- ram_out_rd_dat;
sla_out_ram_miso.rdval <= ram_out_rd_val; -- ram_out_rd_val;
ram_out_rd_adr <= sla_in_ram_mosi.address(c_ram.adr_w-1 DOWNTO 0);
ram_out_rd_en <= sla_in_ram_mosi.rd;
sla_out_ram_miso.rddata(c_ram.dat_w-1 DOWNTO 0) <= ram_out_rd_dat;
sla_out_ram_miso.rdval <= ram_out_rd_val;
nxt_cycle_cnt <= cycle_cnt +1;
END IF;
END PROCESS;
......@@ -628,4 +572,4 @@ BEGIN
END str;
END rtl;
-- Daniel's suggested restructured st_hitogram.vhd.
LIBRARY IEEE, common_lib, mm_lib, technology_lib, dp_lib;
USE IEEE.std_logic_1164.ALL;
USE common_lib.common_pkg.ALL;
USE common_lib.common_mem_pkg.ALL;
USE dp_lib.dp_stream_pkg.ALL;
USE technology_lib.technology_select_pkg.ALL;
ENTITY st_histogram_8_april IS
GENERIC (
g_in_data_w : NATURAL := 14; -- >= 9 when g_nof_bins is 512; (max. c_dp_stream_data_w =768) <-- maybe just g_data_w ??
g_nof_bins : NATURAL := 512; -- is a power of 2 and g_nof_bins <= c_data_span; max. 512
g_nof_data : NATURAL
);
PORT (
dp_rst : IN STD_LOGIC;
dp_clk : IN STD_LOGIC;
-- Streaming
snk_in : IN t_dp_sosi;
-- DP clocked memory bus
ram_mosi : IN t_mem_mosi;
ram_miso : OUT t_mem_miso
);
END st_histogram_8_april;
ARCHITECTURE str OF st_histogram_8_april IS
CONSTANT c_adr_w : NATURAL := ceil_log2(g_nof_bins);
CONSTANT c_ram : t_c_mem := (latency => 1,
adr_w => c_adr_w, -- 9 bits needed to adress/select 512 adresses
dat_w => c_word_w, -- 32bit, def. in common_pkg; >= c_bin_w
nof_dat => g_nof_bins, -- 512 adresses with 32 bit words, so 512
init_sl => '0'); -- MM side : sla_in, sla_out
-- CONSTANT c_mem_miso_setting : t_mem_miso := (rddata => mem_miso_init, -- c_mem_miso_rst; -- limit to 32 bit
-- rdval => '0',
-- waitrequest => '0' );
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
-- SIGNAL mem_miso_init : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0) := (OTHERS => '0');
SIGNAL bin_reader_mosi : 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 common_ram_r_w_0_miso : t_mem_miso := c_mem_miso_rst;
SIGNAL init_phase : STD_LOGIC := '1';
SIGNAL rd_cnt_allowed : 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_pp : STD_LOGIC;
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 prev_wrdata : NATURAL;
SIGNAL prev_prev_wrdata : NATURAL;
SIGNAL sync_detect : STD_LOGIC := '0';
SIGNAL sync_detect_ppp : STD_LOGIC;
-- SIGNAL adr_w : STD_LOGIC_VECTOR(g_in_data_w -1 DOWNTO c_adr_low);
--pipelined signals
SIGNAL dp_pipeline_src_out_p : t_dp_sosi;
SIGNAL dp_pipeline_src_out_pp : t_dp_sosi;
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;
--debug signals
SIGNAL nxt_dbg_sync_detect : STD_LOGIC;
SIGNAL dbg_sync_detect : STD_LOGIC;
SIGNAL dbg_state_string : STRING(1 TO 3) := " ";
BEGIN
-----------------------------------------------------------------------------
-- Bin reader: Convert snk_in data to bin_reader_mosi with read request
-- . in : snk_in (latency: 0)
-- . out : bin_reader_mosi (latency: 0)
-- . out : bin_reader_mosi_pp (latency: 2)
-- - out : rd_cnt_allowed_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);
--snk_in pipeline
u_dp_pipeline_snk_in_1_cycle : ENTITY dp_lib.dp_pipeline
GENERIC MAP (
g_pipeline => 1 -- 0 for wires, > 0 for registers,
)
PORT MAP (
rst => dp_rst,
clk => dp_clk,
snk_in => snk_in,
src_out => dp_pipeline_src_out_p
);
init_phase <= '0' WHEN dp_pipeline_src_out_p.sync = '1';
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 => dp_pipeline_src_out_pp
);
toggle_detect_false <= '0' WHEN dp_pipeline_src_out_pp.sync = '1';
sync_detect <= '1' 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
-- GENERIC MAP (
-- 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
-- );
u_common_pipeline_sl_sync_detect_3_cycle : ENTITY common_lib.common_pipeline_sl
GENERIC MAP(
g_pipeline => 3 -- 0 for wires, > 0 for registers,
)
PORT MAP (
clk => dp_clk,
in_dat => sync_detect,
out_dat => sync_detect_ppp
);
--prev_bin_reader_mosi pipeline
-- u_dp_pipeline_bin_reader_mosi_1_cycle : ENTITY dp_lib.dp_pipeline
-- GENERIC MAP (
-- g_pipeline => 1 -- 0 for wires, > 0 for registers,
-- )
-- PORT MAP (
-- rst => dp_rst,
-- clk => dp_clk,
-- snk_in => bin_reader_mosi,
-- src_out => prev_bin_reader_mosi
-- );
u_common_pipeline_bin_reader_mosi_1_cycle : ENTITY common_lib.common_pipeline
GENERIC MAP (
g_representation => "UNSIGNED", --orig. signed
g_pipeline => 1,
g_in_dat_w => c_adr_w, -- c_mem_address_w
g_out_dat_w => c_adr_w
)
PORT MAP (
clk => dp_clk,
clken => bin_reader_mosi.rd, -- '1',
in_dat => STD_LOGIC_VECTOR(bin_reader_mosi.address(c_adr_w-1 DOWNTO 0)),
out_dat => prev_bin_reader_mosi.address(c_adr_w-1 DOWNTO 0)
);
u_common_pipeline_bin_reader_mosi_2_cycle : ENTITY common_lib.common_pipeline -- better to pipeline prev_bin_reader_mosi??
GENERIC MAP (
g_representation => "UNSIGNED", --orig. signed
g_pipeline => 1,
g_in_dat_w => c_adr_w,
g_out_dat_w => c_adr_w
)
PORT MAP (
clk => dp_clk,
in_dat => STD_LOGIC_VECTOR(prev_bin_reader_mosi.address(c_adr_w-1 DOWNTO 0)),
out_dat => bin_reader_mosi_pp.address(c_adr_w-1 DOWNTO 0)
);
u_common_pipeline_bin_reader_mosi_3_cycle : ENTITY common_lib.common_pipeline -- better to pipeline prev_bin_reader_mosi??
GENERIC MAP (
g_representation => "UNSIGNED", --orig. signed
g_pipeline => 2,
g_in_dat_w => c_adr_w,
g_out_dat_w => c_adr_w
)
PORT MAP (
clk => dp_clk,
in_dat => STD_LOGIC_VECTOR(prev_bin_reader_mosi.address(c_adr_w-1 DOWNTO 0)),
out_dat => bin_reader_mosi_ppp.address(c_adr_w-1 DOWNTO 0)
);
--bin_reader_mosi_pp pipeline
-- u_dp_pipeline_bin_reader_mosi_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 => 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_pp pipeline
u_common_pipeline_sl_rd_cnt_allowed : ENTITY common_lib.common_pipeline_sl
GENERIC MAP(
g_pipeline => 2 -- 0 for wires, > 0 for registers,
)
PORT MAP (
clk => dp_clk,
in_dat => rd_cnt_allowed,
out_dat => rd_cnt_allowed_pp
);
toggle_detect <= '1' 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')
u_common_pipeline_sl_toggle_detect : ENTITY common_lib.common_pipeline_sl
GENERIC MAP(
g_pipeline => 2 -- 0 for wires, > 0 for registers,
)
PORT MAP (
clk => dp_clk,
in_dat => toggle_detect,
out_dat => toggle_detect_pp
);
-----------------------------------------------------------------------------
-- Bin writer : increments current bin value and sets up write request
-- . in : toggle_detect_pp (latency: 2)
-- . in : bin_reader_mosi_pp (latency: 2)
-- . in : common_ram_r_w_0_miso (latency: 2)
-- . in : rd_cnt_allowed_pp (latency: 2)
-- . 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,
bin_reader_mosi_pp.address, toggle_detect, rd_cnt_allowed_pp, rd_adr_cnt, init_phase, prev_wrdata, prev_prev_wrdata, sync_detect_ppp) IS
BEGIN
nxt_bin_writer_mosi <= c_mem_mosi_rst;
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
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.address <= bin_reader_mosi_pp.address; --TODO: what other input do we need for this? -- becomes bin_reader_mosi.address
-- reset count? if toggle detected copy count to toggle counter
nxt_prev_wrdata <= TO_UINT(common_ram_r_w_0_miso.rddata) + 1;
-- nxt_rd_adr_cnt <= 0; -- really necessary ??
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 -- dp_pipeline_src_out_pp: 2
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.address <= bin_reader_mosi_pp.address;
-- nxt_toggle_adr_cnt <= 0;
nxt_prev_wrdata <= prev_prev_wrdata+1;
dbg_state_string <= "td ";
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';
-- IF sync_detect_ppp = '1' THEN
-- 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;
dbg_state_string <= "r# ";
-- END IF;
nxt_bin_writer_mosi.address <= bin_reader_mosi_pp.address;
ELSIF sync_detect_ppp = '1' THEN -- snk_in.sync at least -- good as it is!
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.address <= bin_reader_mosi_pp.address;
-- nxt_rd_adr_cnt <= 0; -- really necessary ??
nxt_prev_wrdata <= 1;
nxt_dbg_sync_detect <= '1';
dbg_state_string <= "sd ";
END IF;
END PROCESS;
p_bin_writer_mosi : PROCESS(dp_clk, dp_rst, nxt_bin_writer_mosi, nxt_rd_adr_cnt, nxt_prev_wrdata) IS
BEGIN
IF dp_rst = '1' THEN
bin_writer_mosi <= c_mem_mosi_rst;
ELSIF RISING_EDGE(dp_clk) THEN
bin_writer_mosi <= nxt_bin_writer_mosi;
-- rd_adr_cnt <= nxt_rd_adr_cnt;
-- toggle_adr_cnt <= nxt_toggle_adr_cnt;
prev_wrdata <= nxt_prev_wrdata;
prev_prev_wrdata<= prev_wrdata;
END IF;
END PROCESS;
-- . Compare adress with the two previous adresses and if:
-- . it is the same as the last adress increase a counter
-- . it is the same as 2 cycles back but not the last copy the data to be
-- written directly into the counter instead of trying to read (ask) it
-- back from RAM at the same clock cycle (which is impossible)
-- . it is not the same enable the nxt_wr_dat data to be written
-- at the next cycle by making nxt_wr_en high
-- . Write the wr_dat data to the RAM
-----------------------------------------------------------------------------
-- Bin Arbiter: Determine next RAM access
-- . in : bin_reader_mosi (latency: 0)
-- : init_phase (latency: 0)
-- : prev_bin_reader_mosi (latency: 1)
-- : bin_writer_mosi (latency: 3)
-- . out : bin_arbiter_rd_mosi (latency: 1)
-- . : 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_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'; -- bin_writer_mosi(adress 3cycles ago?) .address when .rd='1' ????
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
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;
-----------------------------------------------------------------------------
-- RAM that contains the bins
-- . in : bin_arbiter_wr_mosi (latency: 4)
-- . in : bin_arbiter_rd_mosi (latency: 1)
-- . out : common_ram_r_w_0_miso (latency: 2)
-----------------------------------------------------------------------------
common_ram_r_w_0: ENTITY common_lib.common_ram_r_w
GENERIC MAP (
g_technology => c_tech_select_default,
g_ram => c_ram,
g_init_file => "UNUSED"
)
PORT MAP (
rst => dp_rst,
clk => dp_clk,
clken => '1',
wr_en => bin_arbiter_wr_mosi.wr,
wr_adr => bin_arbiter_wr_mosi.address(c_adr_w-1 DOWNTO 0),
wr_dat => bin_arbiter_wr_mosi.wrdata(c_word_w-1 DOWNTO 0),
rd_en => bin_arbiter_rd_mosi.rd,
rd_adr => bin_arbiter_rd_mosi.address(c_adr_w-1 DOWNTO 0),
rd_dat => common_ram_r_w_0_miso.rddata(c_word_w-1 DOWNTO 0),
rd_val => common_ram_r_w_0_miso.rdval
);
p_debug : PROCESS(nxt_dbg_sync_detect) IS
BEGIN
dbg_sync_detect <= '0';
IF nxt_dbg_sync_detect = '1' THEN
dbg_sync_detect <= '1';
END IF;
END PROCESS;
END str;
......@@ -23,7 +23,20 @@
-- Author: J.W.E. Oudman
-- Purpose: Provide MM slave register for st_histogram
-- Description:
-- Because the st_histogram component uses 2 RAM blocks that are swapped
-- after every sync pulse, both blocks have to work in the dp clock domain
-- and the Memory Mapped bus coming out of the component consequently also
-- works in the dp clock domain.
--
-- To convert the signals to the mm clock domain the common_reg_cross_domain
-- component is used. Because the inner workings of that component is
-- dependent on some components that take time to reliably stabialize the
-- conversion takes 12 mm clock cycles before the next address may be
-- requested.
--
--
-- [Alternative: shared dual clocked RAM block]
--
--
-------------------------------------------------------------------------------
......@@ -35,12 +48,10 @@ USE dp_lib.dp_stream_pkg.ALL;
--USE technology_lib.technology_select_pkg.ALL;
ENTITY st_histogram_reg IS
GENERIC (
-- g_in_data_w : NATURAL := 14; -- >= 9 when g_nof_bins is 512; (max. c_dp_stream_data_w =768)
-- GENERIC (
-- g_nof_bins : NATURAL := 512; -- is a power of 2 and g_nof_bins <= c_data_span; max. 512
-- g_nof_data : NATURAL; --
g_str : STRING := "freq.density" -- to select output to MM bus ("frequency" or "freq.density")
);
-- g_str : STRING := "freq.density" -- to select output to MM bus ("frequency" or "freq.density")
-- );
PORT (
dp_rst : IN STD_LOGIC;
dp_clk : IN STD_LOGIC;
......@@ -67,40 +78,10 @@ ARCHITECTURE str OF st_histogram_reg IS
-- nof_dat => 1,
-- init_sl => g_default_value);
-- SIGNAL mm_xonoff_reg : STD_LOGIC_VECTOR(0 DOWNTO 0);
SIGNAL rd_en : STD_LOGIC_VECTOR(0 DOWNTO 0);
SIGNAL rd_val : STD_LOGIC_VECTOR(0 DOWNTO 0);
BEGIN
-- u_common_spulse_mosi_rd : ENTITY common_lib.common_spulse
-- PORT MAP (
-- in_rst => mm_rst,
-- in_clk => mm_clk,
---- in_clken =>
-- in_pulse => ram_mosi.rd,
-- in_busy => OPEN,
-- out_rst => dp_rst,
-- out_clk => dp_clk,
---- out_clken =>
-- out_pulse => mas_out_ram_mosi.rd
-- );
-- u_common_reg_cross_domain_mosi_rd : ENTITY common_lib.common_reg_cross_domain
-- PORT MAP (
-- in_rst => mm_rst,
-- in_clk => mm_clk,
--
-- in_dat => slv(ram_mosi.rd),
--
-- out_rst => dp_rst,
-- out_clk => dp_clk,
--
-- out_dat => rd_en
-- );
--
-- mas_out_ram_mosi.rd <= rd_en(0);
u_common_reg_cross_domain_mosi_address : ENTITY common_lib.common_reg_cross_domain
PORT MAP (
in_rst => mm_rst,
......@@ -116,34 +97,6 @@ BEGIN
out_new => mas_out_ram_mosi.rd
);
-- u_common_spulse_miso_rdval : ENTITY common_lib.common_spulse
-- PORT MAP (
-- in_rst => dp_rst,
-- in_clk => dp_clk,
---- in_clken =>
-- in_pulse => mas_in_ram_miso.rdval,
-- in_busy => OPEN,
-- out_rst => mm_rst,
-- out_clk => mm_clk,
---- out_clken =>
-- out_pulse => ram_miso.rdval
-- );
-- u_reg_cross_domain_miso_rdval : ENTITY common_lib.common_reg_cross_domain
-- PORT MAP (
-- in_rst => dp_rst,
-- in_clk => dp_clk,
--
-- in_dat => slv(mas_in_ram_miso.rdval),
--
-- out_rst => mm_rst,
-- out_clk => mm_clk,
--
-- out_dat => rd_val
-- );
-- ram_miso.rdval <= rd_val(0);
u_reg_cross_domain_miso_rddata : ENTITY common_lib.common_reg_cross_domain
PORT MAP (
in_rst => dp_rst,
......@@ -158,4 +111,5 @@ BEGIN
out_dat => ram_miso.rddata,
out_new => ram_miso.rdval
);
END str;
-------------------------------------------------------------------------------
--
-- 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: Testing the st_histogram component on it's pecularities
-- Description:
-- The st_histogram component is mainly about saving counter data and
-- making the saved data available for the MM master. The working of the
-- RAM blocks has a big influence on this. That is why the testbench is made
-- 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
-- a simple counter is sufficient.
--
-- 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
-- same time, a special situation can happen where the addresses can toggle
-- (e.g. 0; 1; 0; 1) which causes incorrect counting. To simulate this the
-- g_snk_in_data_sim_type can be set to 'toggle'
--
-- 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
-- valid data (or not) where snk_in.valid = '0' by setting the g_valid_gap
-- to TRUE or FALSE.
--
-------------------------------------------------------------------------------
LIBRARY IEEE, common_lib, mm_lib, dp_lib;
USE IEEE.std_logic_1164.ALL;
USE common_lib.common_pkg.ALL;
USE common_lib.common_mem_pkg.ALL;
USE common_lib.tb_common_pkg.ALL;
USE dp_lib.dp_stream_pkg.ALL;
ENTITY tb_st_histogram IS
GENERIC(
g_sync_length : NATURAL := 200;
g_nof_sync : NATURAL := 3;
g_data_w : NATURAL := 4;
g_nof_bins : NATURAL := 8;
g_data_w : NATURAL := 4; --4 ; 1
g_nof_bins : NATURAL := 8; --8 ; 2
g_nof_data : NATURAL := 200;
g_str : STRING := "freq.density";
g_valid_gap : BOOLEAN := FALSE;
g_snk_in_data_sim_type : STRING := "counter" -- "counter" or "toggle"
--g_str : STRING := "freq.density";
g_valid_gap : BOOLEAN := TRUE;
g_snk_in_data_sim_type : STRING := "mix" -- "counter" or "toggle" or "mix"
);
END tb_st_histogram;
ARCHITECTURE tb OF tb_st_histogram IS
-- CONSTANT c_mm_init_time : NATURAL := 5; -- <--
CONSTANT c_adr_w : NATURAL := ceil_log2(g_nof_bins);
CONSTANT c_adr_low_calc : INTEGER := g_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
--SIGNAL position : INTEGER range g_data_w'RANGE;
CONSTANT c_dp_inti_time : NATURAL := 5;
SIGNAL tb_end : STD_LOGIC := '0';
SIGNAL pre_valid : STD_LOGIC := '0';
SIGNAL prev_unvalid : STD_LOGIC := '0';
SIGNAL init_phase : STD_LOGIC := '1';
SIGNAL toggle_start : STD_LOGIC := '0';
----------------------------------------------------------------------------
-- Clocks and resets
----------------------------------------------------------------------------
-- CONSTANT c_mm_clk_period : TIME := 20 ns; -- <--
CONSTANT c_dp_clk_period : TIME := 5 ns;
-- SIGNAL mm_rst : STD_LOGIC := '1'; -- <--
-- SIGNAL mm_clk : STD_LOGIC := '1';
SIGNAL dp_rst : STD_LOGIC;
SIGNAL dp_clk : STD_LOGIC := '1';
......@@ -53,9 +104,6 @@ BEGIN
----------------------------------------------------------------------------
-- Clock and reset generation
----------------------------------------------------------------------------
-- mm_clk <= NOT mm_clk OR tb_end AFTER c_mm_clk_period/2; -- <--
-- mm_rst <= '1', '0' AFTER c_mm_clk_period*c_mm_init_time;
dp_clk <= NOT dp_clk OR tb_end AFTER c_dp_clk_period/2;
dp_rst <= '1', '0' AFTER c_dp_clk_period*c_dp_inti_time;
......@@ -63,30 +111,76 @@ BEGIN
----------------------------------------------------------------------------
-- Source: counter stimuli
-- Source: stimuli
-- st_histogram_snk_in.data counter or toggle stimuli
-- .valid with or without gap's in valid stimuli
-- .sync sync stimuli
----------------------------------------------------------------------------
-- st_histogram_snk_in.data(g_data_w-1 DOWNTO 0) <= (OTHERS=>'0') WHEN dp_rst='1' ELSE INCR_UVEC(st_histogram_snk_in.data(g_data_w-1 DOWNTO 0), 1) WHEN rising_edge(dp_clk) AND st_histogram_snk_in.valid='1';
init_phase <= '0' WHEN st_histogram_snk_in.sync = '1';
p_data : PROCESS(dp_rst, dp_clk, st_histogram_snk_in)
BEGIN
IF g_snk_in_data_sim_type = "counter" THEN
IF dp_rst='1' THEN
st_histogram_snk_in.data(g_data_w-1 DOWNTO 0) <= (OTHERS=>'0');
ELSIF rising_edge(dp_clk) AND st_histogram_snk_in.valid='1' THEN
st_histogram_snk_in.data(g_data_w-1 DOWNTO 0) <= INCR_UVEC(st_histogram_snk_in.data(g_data_w-1 DOWNTO 0), 1);
ELSIF rising_edge(dp_clk) AND pre_valid='1' THEN -- st_histogram_snk_in.valid='1' THEN -- maybe needs init_cnt_start = '1' instead?
IF prev_unvalid = '0' THEN
st_histogram_snk_in.data(g_data_w-1 DOWNTO 0) <= INCR_UVEC(st_histogram_snk_in.data(g_data_w-1 DOWNTO 0), 1);
ELSIF prev_unvalid = '1' THEN
st_histogram_snk_in.data(g_data_w-1 DOWNTO 0) <= INCR_UVEC(st_histogram_snk_in.data(g_data_w-1 DOWNTO 0), -1);
prev_unvalid <= '0';
END IF;
ELSIF rising_edge(dp_clk) AND pre_valid='0' AND init_phase='0' THEN -- st_histogram_snk_in.valid='0' AND init_phase = '0' THEN
IF prev_unvalid = '0' THEN
st_histogram_snk_in.data(g_data_w-1 DOWNTO 0) <= INCR_UVEC(st_histogram_snk_in.data(g_data_w-1 DOWNTO 0), 2);
prev_unvalid <= '1';
END IF;
END IF;
ELSIF g_snk_in_data_sim_type = "toggle" THEN
IF dp_rst='1' THEN
st_histogram_snk_in.data(g_data_w-1 DOWNTO 0) <= (OTHERS=>'0');
ELSIF rising_edge(dp_clk) AND st_histogram_snk_in.valid='1' THEN
IF st_histogram_snk_in.data(g_data_w-1 DOWNTO 0) = TO_UVEC(0, g_data_w) THEN
st_histogram_snk_in.data(g_data_w-1 DOWNTO 0) <= TO_UVEC(1, g_data_w);
ELSIF rising_edge(dp_clk) AND st_histogram_snk_in.valid='1' THEN -- maybe needs init_cnt_start = '1' instead?
IF st_histogram_snk_in.data(g_data_w-1 DOWNTO 0) = TO_UVEC(0, g_data_w) THEN -- c_adr_low
st_histogram_snk_in.data(c_adr_low) <= '1'; -- TO_UVEC(1, g_data_w); --g_data_w-1 DOWNTO 0
ELSE
st_histogram_snk_in.data(g_data_w-1 DOWNTO 0) <= TO_UVEC(0, g_data_w);
END IF;
END IF;
ELSIF g_snk_in_data_sim_type = "mix" THEN
IF toggle_start = '1' THEN
-- toggle part
IF dp_rst='1' THEN
st_histogram_snk_in.data(g_data_w-1 DOWNTO 0) <= (OTHERS=>'0');
ELSIF rising_edge(dp_clk) AND st_histogram_snk_in.valid='1' THEN -- maybe needs init_cnt_start = '1' instead?
IF st_histogram_snk_in.data(g_data_w-1 DOWNTO 0) = TO_UVEC(0, g_data_w) THEN -- c_adr_low
st_histogram_snk_in.data(c_adr_low) <= '1'; -- TO_UVEC(1, g_data_w); --g_data_w-1 DOWNTO 0
ELSE
st_histogram_snk_in.data(g_data_w-1 DOWNTO 0) <= TO_UVEC(0, g_data_w);
END IF;
END IF;
-- end toggle part
ELSE
-- counter part
IF dp_rst='1' THEN
st_histogram_snk_in.data(g_data_w-1 DOWNTO 0) <= (OTHERS=>'0');
ELSIF rising_edge(dp_clk) AND pre_valid='1' THEN -- st_histogram_snk_in.valid='1' THEN -- maybe needs init_cnt_start = '1' instead?
IF prev_unvalid = '0' THEN
st_histogram_snk_in.data(g_data_w-1 DOWNTO 0) <= INCR_UVEC(st_histogram_snk_in.data(g_data_w-1 DOWNTO 0), 1);
ELSIF prev_unvalid = '1' THEN
st_histogram_snk_in.data(g_data_w-1 DOWNTO 0) <= INCR_UVEC(st_histogram_snk_in.data(g_data_w-1 DOWNTO 0), -1);
prev_unvalid <= '0';
END IF;
ELSIF rising_edge(dp_clk) AND pre_valid='0' AND init_phase='0' THEN -- st_histogram_snk_in.valid='0' AND init_phase = '0' THEN
IF prev_unvalid = '0' THEN
st_histogram_snk_in.data(g_data_w-1 DOWNTO 0) <= INCR_UVEC(st_histogram_snk_in.data(g_data_w-1 DOWNTO 0), 2);
prev_unvalid <= '1';
END IF;
END IF;
-- end counter part
END IF;
END IF;
END PROCESS;
......@@ -94,125 +188,69 @@ BEGIN
p_stimuli : PROCESS
BEGIN
IF g_valid_gap = FALSE THEN
-- dp_rst <= '1';
-- initializing
st_histogram_snk_in.sync <= '0';
st_histogram_snk_in.valid <= '0';
WAIT UNTIL rising_edge(dp_clk);
-- FOR I IN 0 TO 9 LOOP WAIT UNTIL rising_edge(dp_clk); END LOOP;
-- dp_rst <= '0';
FOR I IN 0 TO 9 LOOP WAIT UNTIL rising_edge(dp_clk); END LOOP;
pre_valid <= '1';
st_histogram_snk_in.valid <= '1';
-- generating g_nof_sync sync pulses with g_sync_length cycles between
FOR I IN 0 TO g_nof_sync-1 LOOP
toggle_start <= '1';
st_histogram_snk_in.sync <= '1';
WAIT UNTIL rising_edge(dp_clk);
st_histogram_snk_in.sync <= '0';
FOR I IN 0 TO g_sync_length-1 LOOP WAIT UNTIL rising_edge(dp_clk); END LOOP;
proc_common_wait_some_cycles(dp_clk, 2);
toggle_start <= '0';
FOR I IN 0 TO g_sync_length-1 LOOP WAIT UNTIL rising_edge(dp_clk); END LOOP; -- -4 ipv -1 ?
END LOOP;
-- ending
FOR I IN 0 TO 9 LOOP WAIT UNTIL rising_edge(dp_clk); END LOOP;
tb_end <= '1';
WAIT;
ELSIF g_valid_gap = TRUE THEN
---------------------------------------------
-- temp copy procedure: proc_dp_gen_block_data
---------------------------------------------
-- sync_nr <= 0;
-- block_nr <= 0;
--
-- cnt_sync <= '0';
-- cnt_val <= '0';
-- cnt_dat <= (cnt_dat'RANGE=>'1'); -- -1, so first valid cnt_dat starts at 0
--
-- -- allow some clock cycles before start after rst release
-- WAIT UNTIL rst='0';
-- FOR I IN 0 TO c_start_delay-1 LOOP WAIT UNTIL rising_edge(clk); END LOOP;
--
-- -- output first sync
-- cnt_sync <= '1';
-- WAIT UNTIL rising_edge(clk);
-- cnt_sync <= '0';
-- FOR I IN 1 TO c_gap_size-1 LOOP WAIT UNTIL rising_edge(clk); END LOOP;
--
-- WHILE TRUE LOOP
-- -- output block
-- IF c_throttle_num >= c_throttle_den THEN
-- -- no need to throttle, so cnt_val active during whole data block
-- FOR I IN 0 TO c_block_size-1 LOOP
-- cnt_val <= '1';
-- cnt_dat <= INCR_UVEC(cnt_dat, 1);
-- WAIT UNTIL rising_edge(clk);
-- END LOOP;
-- ELSE
-- -- throttle cnt_val, so c_throttle_num active cnt_val cycles per c_throttle_den cycles
-- FOR I IN 0 TO c_block_size/c_throttle_num-1 LOOP
-- FOR J IN 0 TO c_throttle_num-1 LOOP
-- cnt_val <= '1';
-- cnt_dat <= INCR_UVEC(cnt_dat, 1);
-- WAIT UNTIL rising_edge(clk);
-- END LOOP;
-- FOR J IN 0 TO c_throttle_den-c_throttle_num-1 LOOP
-- cnt_val <= '0';
-- WAIT UNTIL rising_edge(clk);
-- END LOOP;
-- END LOOP;
-- END IF;
-- cnt_val <= '0';
-- -- output sync for next block at first sample of gap
-- IF block_nr>0 AND ((block_nr + 1) MOD c_nof_block_per_sync)=0 THEN
-- cnt_sync <= '1';
-- sync_nr <= sync_nr+1;
-- END IF;
-- WAIT UNTIL rising_edge(clk);
-- -- output rest of the gap
-- cnt_sync <= '0';
-- FOR I IN 1 TO c_gap_size-1 LOOP WAIT UNTIL rising_edge(clk); END LOOP;
-- -- next block
-- block_nr <= block_nr+1;
-- END LOOP;
---------------------------------------------
-- end temp copy procedure: proc_dp_gen_block_data
---------------------------------------------
-- dp_rst <= '1';
-- initializing
st_histogram_snk_in.sync <= '0';
st_histogram_snk_in.valid <= '0';
WAIT UNTIL rising_edge(dp_clk);
-- FOR I IN 0 TO 9 LOOP WAIT UNTIL rising_edge(dp_clk); END LOOP;
-- dp_rst <= '0';
FOR I IN 0 TO 9 LOOP WAIT UNTIL rising_edge(dp_clk); END LOOP;
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';
WAIT UNTIL rising_edge(dp_clk);
st_histogram_snk_in.sync <= '0';
FOR I IN 0 TO (g_sync_length/2)-1 LOOP WAIT UNTIL rising_edge(dp_clk); END LOOP;
proc_common_wait_some_cycles(dp_clk, 2);
toggle_start <= '0';
FOR I IN 0 TO (g_sync_length/2)-5 LOOP WAIT UNTIL rising_edge(dp_clk); END LOOP; -- -5 ipv -2 ?
pre_valid <= '0';
WAIT UNTIL rising_edge(dp_clk);
st_histogram_snk_in.valid <= '0';
pre_valid <= '1'; -- gap 1 clock cycles
WAIT UNTIL rising_edge(dp_clk);
--WAIT UNTIL rising_edge(dp_clk);
--WAIT UNTIL rising_edge(dp_clk);
--WAIT UNTIL rising_edge(dp_clk); -- gap 2 clock cycles
--WAIT UNTIL rising_edge(dp_clk); -- gap 3 clock cycles
st_histogram_snk_in.valid <= '1';
FOR I IN 0 TO (g_sync_length/4)-1 LOOP WAIT UNTIL rising_edge(dp_clk); END LOOP;
FOR I IN 0 TO (g_sync_length/4)-2 LOOP WAIT UNTIL rising_edge(dp_clk); END LOOP;
pre_valid <= '0';
WAIT UNTIL rising_edge(dp_clk);
st_histogram_snk_in.valid <= '0';
WAIT UNTIL rising_edge(dp_clk);
--st_histogram_snk_in.valid <= '0';
--st_histogram_snk_in.valid <= '0'; -- gap while sync
st_histogram_snk_in.sync <= '1';
pre_valid <= '1';
WAIT UNTIL rising_edge(dp_clk);
st_histogram_snk_in.valid <= '1';
st_histogram_snk_in.sync <= '0';
FOR I IN 0 TO (g_sync_length/4)-1 LOOP WAIT UNTIL rising_edge(dp_clk); END LOOP;
END LOOP;
-- ending
FOR I IN 0 TO 9 LOOP WAIT UNTIL rising_edge(dp_clk); END LOOP;
tb_end <= '1';
WAIT;
......@@ -225,12 +263,12 @@ BEGIN
-- DUT: Device Under Test
----------------------------------------------------------------------------
u_st_histogram : ENTITY work.st_histogram
u_st_histogram : ENTITY work.st_histogram_8_april
GENERIC MAP(
g_in_data_w => g_data_w,
g_nof_bins => g_nof_bins,
g_nof_data => g_nof_data,
g_str => g_str
g_nof_data => g_nof_data
--g_str => g_str
)
PORT MAP (
dp_rst => dp_rst,
......@@ -240,8 +278,8 @@ BEGIN
snk_in => st_histogram_snk_in,
-- Memory Mapped
sla_in_ram_mosi => c_mem_mosi_rst,
sla_out_ram_miso => OPEN
ram_mosi => c_mem_mosi_rst,-- sla_in_
ram_miso => OPEN -- sla_out_
);
END tb;
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment