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

-Added data reduction/counting code to st_histogram to solve

simultaneous read/write issue;
-Added signed/unsigned histogram readout to TB;
-All test benches pass OK.
parent b7e62e81
No related branches found
No related tags found
1 merge request!137st_histogram updates. Ready for integration in LOFAR2.
......@@ -88,7 +88,7 @@ ENTITY st_histogram IS
GENERIC (
g_data_w : NATURAL := 8;
g_nof_bins : NATURAL := 256;
g_nof_data_per_sync : NATURAL := 1024;
g_nof_data_per_sync : NATURAL := 1024; -- must be larger than g_nof_bins
g_data_type : STRING := "unsigned" -- unsigned or signed
);
PORT (
......@@ -115,7 +115,14 @@ ARCHITECTURE rtl OF st_histogram IS
-------------------------------------------------------------------------------
-- snk_in.data help signal
-------------------------------------------------------------------------------
SIGNAL snk_in_data : STD_LOGIC_VECTOR(g_data_w-1 DOWNTO c_adr_low);
SIGNAL snk_in_data : STD_LOGIC_VECTOR(c_ram_adr_w-1 DOWNTO 0);
-------------------------------------------------------------------------------
-- snk_in_reg_arr
-------------------------------------------------------------------------------
SIGNAL snk_in_reg_arr : t_dp_sosi_arr(3 DOWNTO 0);
SIGNAL nxt_snk_in_reg_arr : t_dp_sosi_arr(3 DOWNTO 0);
SIGNAL snk_in_reg : t_dp_sosi;
-------------------------------------------------------------------------------
-- ram_pointer
......@@ -132,11 +139,12 @@ ARCHITECTURE rtl OF st_histogram IS
SIGNAL bin_reader_miso : t_mem_miso;
SIGNAL prv_bin_reader_mosi : t_mem_mosi;
-------------------------------------------------------------------------------
-- bin_writer
-------------------------------------------------------------------------------
SIGNAL bin_reader_to_writer_mosi : t_mem_mosi;
SIGNAL bin_reader_to_writer_mosi : t_mem_mosi;
SIGNAL bin_reader_to_writer_count : NATURAL;
SIGNAL nxt_bin_reader_to_writer_count : NATURAL;
SIGNAL nxt_bin_writer_mosi : t_mem_mosi;
SIGNAL bin_writer_mosi : t_mem_mosi;
......@@ -191,6 +199,14 @@ ARCHITECTURE rtl OF st_histogram IS
SIGNAL nxt_ram_clearing : STD_LOGIC;
SIGNAL debug1 : STD_LOGIC;
SIGNAL debug2 : STD_LOGIC;
BEGIN
-------------------------------------------------------------------------------
......@@ -204,13 +220,102 @@ BEGIN
snk_in_data <= snk_in.data(g_data_w-1 DOWNTO c_adr_low);
END GENERATE;
-------------------------------------------------------------------------------
-- Slightly reduce the incoming data to prevent simultineous read/write
-- . Take out every 2nd and 3rd duplicate data value (set valid='0')
-- . Put the number of duplicates in the channel field to be applied downstream
-- . With a RAM read->write latency of 2 cycles, we need a shift register of 3
-- words (0,1,2) deep to prevent simultaneous read/writes on the RAM.
-- . A sequence of duplicate data could cross a sync period:
-- . We need to stop&restart counting duplicates on a sync, don't count
-- across sync periods
-- . We can still get a read on cycle n and a write on cycle n+2 on the
-- same address, but that does not matter as the read,write will be on
-- different RAM blocks (1 RAM block per sync period).
-- . snk_in_reg_arr(0).sync='1' : Don't compare with older snk_in_reg_arr(1)
-- and (2)
-- . snk_in_reg_arr(1).sync='1' : Don't compare with older (2)
-- . snk_in_reg_arr(2).sync='1' : OK to compare with both (1) and (0)
-- . Input : snk_in
-- . Output: snk_in_reg
-------------------------------------------------------------------------------
p_nxt_snk_in_reg_arr: PROCESS(snk_in, snk_in_data, snk_in_reg_arr) IS
BEGIN
FOR i IN 0 TO 3 LOOP
nxt_snk_in_reg_arr(i) <= c_dp_sosi_rst;
END LOOP;
IF snk_in.valid='1' THEN
-- The base function is a shift register
nxt_snk_in_reg_arr(0) <= snk_in;
nxt_snk_in_reg_arr(0).data(c_ram_adr_w-1 DOWNTO 0) <= snk_in_data; -- Use the ranged data
nxt_snk_in_reg_arr(1) <= snk_in_reg_arr(0);
nxt_snk_in_reg_arr(2) <= snk_in_reg_arr(1);
nxt_snk_in_reg_arr(3) <= snk_in_reg_arr(2);
-- Assign a count of 1 to valid data
nxt_snk_in_reg_arr(0).channel <= TO_DP_CHANNEL(1);
IF snk_in_reg_arr(2).valid = '1' THEN -- Shift register 0,1,2 filled with valid data
-- Overwrite channel field (=count) when duplicate data is found
IF snk_in_reg_arr(1).data(g_data_w-1 DOWNTO 0) = snk_in_reg_arr(2).data(g_data_w-1 DOWNTO 0) THEN
-- 1=2
IF snk_in_reg_arr(1).sync = '0' THEN -- Don't count across sync periods
nxt_snk_in_reg_arr(2).valid <= '0';
nxt_snk_in_reg_arr(2).channel <= TO_DP_CHANNEL(0);
nxt_snk_in_reg_arr(3).channel <= TO_DP_CHANNEL(2);
END IF;
END IF;
IF snk_in_reg_arr(0).data(g_data_w-1 DOWNTO 0) = snk_in_reg_arr(1).data(g_data_w-1 DOWNTO 0) THEN
IF snk_in_reg_arr(0).sync = '0' THEN -- Don't count across sync periods
IF snk_in_reg_arr(1).data(g_data_w-1 DOWNTO 0) = snk_in_reg_arr(2).data(g_data_w-1 DOWNTO 0) THEN
-- 0=1=2
IF snk_in_reg_arr(1).sync = '0' THEN -- Don't count across sync periods
nxt_snk_in_reg_arr(1).valid <= '0';
nxt_snk_in_reg_arr(1).channel <= TO_DP_CHANNEL(0);
nxt_snk_in_reg_arr(2).valid <= '0';
nxt_snk_in_reg_arr(2).channel <= TO_DP_CHANNEL(0);
nxt_snk_in_reg_arr(3).channel <= TO_DP_CHANNEL(3);
END IF;
ELSE
-- 0=1
-- Do nothing, otherwise we will never see 0=1=2. Instead wait until 0,1 shifted to 1,2.
END IF;
END IF;
ELSIF snk_in_reg_arr(0).data(g_data_w-1 DOWNTO 0) = snk_in_reg_arr(2).data(g_data_w-1 DOWNTO 0) THEN
-- 0=2
IF snk_in_reg_arr(0).sync = '0' THEN -- Don't count across sync periods
nxt_snk_in_reg_arr(1).valid <= '0';
nxt_snk_in_reg_arr(1).channel <= TO_DP_CHANNEL(0);
nxt_snk_in_reg_arr(3).channel <= TO_DP_CHANNEL(2);
END IF;
END IF;
END IF;
END IF;
END PROCESS;
snk_in_reg <= snk_in_reg_arr(3);
-- Registers
p_snk_in_reg_arr: PROCESS(dp_clk, dp_rst) IS
BEGIN
FOR i IN 0 TO 3 LOOP
IF dp_rst = '1' THEN
snk_in_reg_arr(i) <= c_dp_sosi_rst;
ELSIF RISING_EDGE(dp_clk) THEN
snk_in_reg_arr(i) <= nxt_snk_in_reg_arr(i);
END IF;
END LOOP;
END PROCESS;
-------------------------------------------------------------------------------
-- ram_pointer: Keep track of what RAM to target
-- . Target either RAM 0 or 1 per sync period
-- . RD/WR sides of RAM have shifted sync periods due to rd>wr latency
-- . e.g. a new sync period is read while an old sync period is written
-- . Solution: treat the RAM pointer as MS address bit in separate RD/WR buses
-- . ram_pointer is synchronous to snk_in.sync
-- . ram_pointer is synchronous to snk_in_reg.sync
-------------------------------------------------------------------------------
p_ram_pointer : PROCESS(dp_rst, dp_clk) IS
BEGIN
......@@ -224,14 +329,14 @@ BEGIN
END PROCESS;
-- Don't toggle the RAM pointer on the first sync as we're already reading the RAM at that point.
nxt_toggle_ram_pointer <= '1' WHEN snk_in.sync='1' ELSE toggle_ram_pointer;
nxt_toggle_ram_pointer <= '1' WHEN snk_in_reg.sync='1' ELSE toggle_ram_pointer;
-- Toggle the RAM pointer starting from 2nd sync onwards
ram_pointer <= NOT prv_ram_pointer WHEN snk_in.sync='1' AND toggle_ram_pointer='1' ELSE prv_ram_pointer;
ram_pointer <= NOT prv_ram_pointer WHEN snk_in_reg.sync='1' AND toggle_ram_pointer='1' ELSE prv_ram_pointer;
-------------------------------------------------------------------------------
-- bin_reader : reads bin from RAM, sends bin to bin_writer.
-- . Input : snk_in (input data stream)
-- . Input : snk_in_reg (input data stream)
-- bin_reader_miso (reply to RAM read request: rddata = bin count)
-- ram_pointer (to put in MOSI buses as MS address bit)
-- . Output : bin_reader_mosi (RAM read request, address = bin)
......@@ -240,16 +345,18 @@ BEGIN
-- Fetch the bin from RAM
bin_reader_mosi.wrdata <= (OTHERS=>'0');
bin_reader_mosi.wr <= '0';
bin_reader_mosi.rd <= snk_in.valid;
bin_reader_mosi.address <= RESIZE_UVEC(ram_pointer & snk_in_data, c_word_w);
bin_reader_mosi.rd <= snk_in_reg.valid;
-- bin_reader_mosi.address <= RESIZE_UVEC(ram_pointer & snk_in_data, c_word_w);
bin_reader_mosi.address <= RESIZE_UVEC(ram_pointer & snk_in_reg.data(c_ram_adr_w-1 DOWNTO 0), c_word_w);
-- Store the rd address as bin_writer needs to know where to write the bin count
p_prv_bin_reader_mosi : PROCESS(dp_clk, dp_rst) IS
BEGIN
IF dp_rst = '1' THEN
prv_bin_reader_mosi <= c_mem_mosi_rst;
prv_bin_reader_mosi <= c_mem_mosi_rst;
bin_reader_to_writer_count <= 0;
ELSIF RISING_EDGE(dp_clk) THEN
prv_bin_reader_mosi <= bin_reader_mosi;
prv_bin_reader_mosi <= bin_reader_mosi;
bin_reader_to_writer_count <= nxt_bin_reader_to_writer_count;
END IF;
END PROCESS;
......@@ -257,17 +364,22 @@ BEGIN
bin_reader_to_writer_mosi.wr <= bin_reader_miso.rdval;
bin_reader_to_writer_mosi.wrdata <= RESIZE_UVEC(bin_reader_miso.rddata(c_ram_dat_w-1 DOWNTO 0), c_mem_data_w);
bin_reader_to_writer_mosi.address <= prv_bin_reader_mosi.address;
nxt_bin_reader_to_writer_count <= TO_UINT(snk_in_reg.channel); -- Use register (_nxt) to align count with rdval instead of snk_in_reg.valid
-------------------------------------------------------------------------------
-- bin_writer : Increment the bin, forward write request to bin_arbiter
-- . Input : bin_reader_to_writer_mosi (from bin_reader = bin + bin count)
-- . Output : bin_writer_mosi (to bin_arbiter = bin + incremented bin count)
-------------------------------------------------------------------------------
-- bin_writer_mosi.rd <= '0';
-- bin_writer_mosi.wr <= bin_reader_to_writer_mosi.wr;
-- bin_writer_mosi.address <= bin_reader_to_writer_mosi.address;
-- bin_writer_mosi.wrdata <= INCR_UVEC(bin_reader_to_writer_mosi.wrdata, 1) WHEN bin_reader_to_writer_mosi.wr='1' ELSE bin_reader_to_writer_mosi.wrdata;
nxt_bin_writer_mosi.rd <= '0';
nxt_bin_writer_mosi.wr <= bin_reader_to_writer_mosi.wr;
nxt_bin_writer_mosi.address <= bin_reader_to_writer_mosi.address;
nxt_bin_writer_mosi.wrdata <= INCR_UVEC(bin_reader_to_writer_mosi.wrdata, 1) WHEN bin_reader_to_writer_mosi.wr='1' ELSE bin_writer_mosi.wrdata;
nxt_bin_writer_mosi.wrdata <= INCR_UVEC(bin_reader_to_writer_mosi.wrdata, bin_reader_to_writer_count) WHEN bin_reader_to_writer_mosi.wr='1' ELSE bin_writer_mosi.wrdata;
-- Register the outputs to bin_arbiter (above we have a combinational adder = propagation delay)
p_bin_writer_mosi : PROCESS(dp_clk, dp_rst) IS
......@@ -290,7 +402,7 @@ BEGIN
-- bin_reader_miso (carries the bins requested by bin_reader)
-------------------------------------------------------------------------------
-- Really simple arbitration: always allow writes, only allow reads when possible (rd_addr != wr_addr).
read_allowed <= FALSE WHEN bin_writer_mosi.wr='1' AND bin_writer_mosi.address=bin_reader_mosi.address ELSE TRUE;
read_allowed <= FALSE WHEN bin_writer_mosi.wr='1' AND bin_reader_mosi.rd='1' AND bin_writer_mosi.address=bin_reader_mosi.address ELSE TRUE;
-- save previous read_allowed
p_prv_read_allowed: PROCESS(dp_rst, dp_clk) IS
BEGIN
......@@ -313,20 +425,30 @@ BEGIN
bin_arbiter_wr_mosi.address <= bin_writer_mosi.address;
-- Loop back the WR data to the RD side when read was not allowed or on second read of same address
p_bin_reader_miso : PROCESS(prv_read_allowed, bin_reader_mosi, bin_reader_miso, bin_writer_mosi, read_allowed, bin_arbiter_rd_miso) IS
p_bin_reader_miso : PROCESS(prv_bin_reader_mosi, prv_read_allowed, bin_reader_mosi, bin_writer_mosi, read_allowed, bin_arbiter_rd_miso) IS
BEGIN
debug1 <= '0';
debug2 <= '0';
bin_reader_miso <= bin_arbiter_rd_miso;
IF prv_bin_reader_mosi.rd = '1' AND prv_read_allowed = FALSE THEN -- Fake succesful readback when read was not allowed
bin_reader_miso.rdval <= '1';
bin_reader_miso.rddata <= bin_writer_mosi.wrdata;
ELSIF read_allowed = TRUE THEN
bin_reader_miso <= bin_arbiter_rd_miso;
ELSIF (prv_bin_reader_mosi.rd = '1' AND bin_reader_mosi.rd='1') AND (prv_bin_reader_mosi.address=bin_reader_mosi.address) THEN -- 2 reads on same address in row: 2nd read is outdated so return wrdata here
bin_reader_miso.rdval <= '1';
bin_reader_miso.rddata <= bin_writer_mosi.wrdata;
END IF;
-- IF prv_bin_reader_mosi.rd = '1' AND prv_read_allowed = FALSE THEN
-- -- Fake succesful readback when read was not allowed
-- bin_reader_miso.rdval <= '1';
-- bin_reader_miso.rddata <= bin_writer_mosi.wrdata;
-- debug1 <= '1';
-- ELSIF read_allowed = TRUE THEN
-- bin_reader_miso <= bin_arbiter_rd_miso;
-- ELSIF (prv_bin_reader_mosi.rd = '1' AND bin_reader_mosi.rd='1') AND (prv_bin_reader_mosi.address=bin_reader_mosi.address) THEN
-- -- 2 reads on same address in row: 2nd read is outdated so return wrdata here
-- debug2 <= '1';
-- bin_reader_miso.rdval <= '1';
-- bin_reader_miso.rddata <= bin_writer_mosi.wrdata;
-- END IF;
END PROCESS;
-- 1) Read bin from RAM (MOSI)
-- 2) Read bin value valid (MISO), increment bin value
-- 3) Write bin to RAM (MOSI)
-------------------------------------------------------------------------------
-- Two RAM (common_ram_r_w) instances. The user can read the histogram from the
......
......@@ -64,9 +64,9 @@ USE dp_lib.tb_dp_pkg.ALL;
ENTITY tb_st_histogram IS
GENERIC(
g_nof_sync : NATURAL := 4; -- We're simulating at least 4 g_nof_sync so both RAMs are written and cleared twice.
g_data_w : NATURAL := 8; -- Determines maximum number of bins (2^g_data_w)
g_nof_bins : NATURAL := 256; -- Lower than or equal to 2^g_data_w. Higher is allowed but makes no sense.
g_nof_data_per_sync : NATURAL := 1000; -- Determines max required RAM data width. e.g. 11b to store max bin count '1024'.
g_data_w : NATURAL := 3; -- Determines maximum number of bins (2^g_data_w)
g_nof_bins : NATURAL := 8; -- Lower than or equal to 2^g_data_w. Higher is allowed but makes no sense.
g_nof_data_per_sync : NATURAL := 20; -- Determines max required RAM data width. e.g. 11b to store max bin count '1024'.
g_stimuli_mode : STRING := "sine"; -- "counter", "dc", "sine" or "random"
g_data_type : STRING := "signed"; -- use "signed" if g_stimuli_mode="sine"
g_lock_sine : BOOLEAN := TRUE -- TRUE to lock the sine wave to Sync - produces sparse histogram with low number of non-zero samples (occuring 2*c_sine_nof_periods)
......@@ -83,6 +83,7 @@ ARCHITECTURE tb OF tb_st_histogram IS
CONSTANT c_nof_levels_per_bin : NATURAL := (2**g_data_w)/g_nof_bins; --e.g. 2 values per bin if g_data_w=9 (512 levels) and g_nof_bins=256
CONSTANT c_ram_dat_w : NATURAL := ceil_log2(g_nof_data_per_sync)+1;
CONSTANT c_ram_adr_w : NATURAL := ceil_log2(g_nof_bins);
---------------------------------------------------------------------------
-- Clocks and resets
......@@ -106,6 +107,7 @@ ARCHITECTURE tb OF tb_st_histogram IS
SIGNAL stimuli_en : STD_LOGIC := '1';
SIGNAL stimuli_src_out : t_dp_sosi;
SIGNAL nxt_stimuli_src_out : t_dp_sosi;
SIGNAL stimuli_src_in : t_dp_siso;
SIGNAL stimuli_count : REAL;
SIGNAL stimuli_data : STD_LOGIC_VECTOR(g_data_w-1 DOWNTO 0);
......@@ -115,26 +117,23 @@ ARCHITECTURE tb OF tb_st_histogram IS
----------------------------------------------------------------------------
-- st_histogram
----------------------------------------------------------------------------
SIGNAL st_histogram_snk_in : t_dp_sosi;
SIGNAL st_histogram_ram_mosi : t_mem_mosi;
SIGNAL st_histogram_ram_miso : t_mem_miso;
SIGNAL st_histogram_snk_in : t_dp_sosi;
SIGNAL st_histogram_ram_mosi : t_mem_mosi;
SIGNAL prv_st_histogram_ram_mosi : t_mem_mosi;
SIGNAL st_histogram_ram_miso : t_mem_miso;
----------------------------------------------------------------------------
-- Automatic verification of RAM readout
----------------------------------------------------------------------------
SIGNAL ram_rd_addr : NATURAL;
SIGNAL prv_ram_rd_addr : NATURAL;
SIGNAL ram_rd_word : STD_LOGIC_VECTOR(c_ram_dat_w-1 DOWNTO 0);
SIGNAL ram_rd_word_int : NATURAL;
SIGNAL ram_rd_word_valid : STD_LOGIC;
SIGNAL nxt_ram_rd_word_valid : STD_LOGIC;
----------------------------------------------------------------------------
-- Automatic verification of RAM readout
----------------------------------------------------------------------------
-- Use these 4 signals to verify histogram by eye in the wave window
SIGNAL histogram_data : NATURAL; -- QuestaSim: Format->Analog
SIGNAL histogram_bin_unsigned : NATURAL;
SIGNAL histogram_bin_signed : INTEGER; -- QuestaSim: Radix->Decimal
SIGNAL histogram_valid : STD_LOGIC;
SIGNAL sum_of_bins : NATURAL;
SIGNAL verification_done : STD_LOGIC;
----------------------------------------------------------------------------
-- Signal to display histogram as 'analog signal' in wave window
----------------------------------------------------------------------------
SIGNAL histogram : NATURAL;
BEGIN
......@@ -154,8 +153,9 @@ BEGIN
p_generate_packets : PROCESS
VARIABLE v_sosi : t_dp_sosi := c_dp_sosi_rst;
BEGIN
nxt_stimuli_src_out <= c_dp_sosi_rst;
stimuli_done <= '0';
stimuli_src_out <= c_dp_sosi_rst;
-- stimuli_src_out <= c_dp_sosi_rst;
proc_common_wait_until_low(dp_clk, dp_rst);
proc_common_wait_some_cycles(dp_clk, 5);
......@@ -164,19 +164,19 @@ BEGIN
FOR I IN 0 TO g_nof_sync-1 LOOP
v_sosi.sync := '1';
v_sosi.data := RESIZE_DP_DATA(v_sosi.data(g_data_w-1 DOWNTO 0)); -- wrap when >= 2**g_data_w
proc_dp_gen_block_data(g_data_w, TO_UINT(v_sosi.data), g_nof_data_per_sync, TO_UINT(v_sosi.channel), TO_UINT(v_sosi.err), v_sosi.sync, v_sosi.bsn, dp_clk, stimuli_en, stimuli_src_in, stimuli_src_out);
proc_dp_gen_block_data(g_data_w, TO_UINT(v_sosi.data), g_nof_data_per_sync, TO_UINT(v_sosi.channel), TO_UINT(v_sosi.err), v_sosi.sync, v_sosi.bsn, dp_clk, stimuli_en, stimuli_src_in, nxt_stimuli_src_out);
END LOOP;
END IF;
-- Generate a DC level that increments every sync
IF g_stimuli_mode="dc" THEN
stimuli_src_out.valid <= '1';
nxt_stimuli_src_out.valid <= '1';
FOR I IN 0 TO g_nof_sync-1 LOOP
stimuli_src_out.data <= INCR_UVEC(stimuli_src_out.data, 1); --all g_nof_data_per_sync cycles
stimuli_src_out.sync <= '1'; -- cycle 0
nxt_stimuli_src_out.data <= INCR_UVEC(stimuli_src_out.data, 1); --all g_nof_data_per_sync cycles
nxt_stimuli_src_out.sync <= '1'; -- cycle 0
WAIT FOR 5 ns;
FOR j IN 1 TO g_nof_data_per_sync-1 LOOP --cycles 1..g_nof_data_per_sync-1
stimuli_src_out.sync <= '0';
nxt_stimuli_src_out.sync <= '0';
WAIT FOR 5 ns;
END LOOP;
END LOOP;
......@@ -184,34 +184,35 @@ BEGIN
-- Generate a sine wave
IF g_stimuli_mode="sine" THEN
stimuli_src_out.valid <= '1';
nxt_stimuli_src_out <= stimuli_src_out;
nxt_stimuli_src_out.valid <= '1';
stimuli_count <= 0.0;
FOR I IN 0 TO g_nof_sync-1 LOOP
stimuli_src_out.data <= (OTHERS=>'0');
stimuli_data <= (OTHERS=>'0');
stimuli_src_out.sync <= '1'; -- cycle 0
-- nxt_stimuli_src_out.data <= (OTHERS=>'0');
-- stimuli_data <= (OTHERS=>'0');
nxt_stimuli_src_out.sync <= '1'; -- cycle 0
WAIT FOR 5 ns;
FOR j IN 1 TO g_nof_data_per_sync-1 LOOP --cycles 1..g_nof_data_per_sync-1
stimuli_src_out.sync <= '0';
stimuli_data <= TO_SVEC( integer(round( c_sine_amplitude * sin(stimuli_count) )), g_data_w);
stimuli_src_out.data(g_data_w-1 DOWNTO 0) <= stimuli_data;
nxt_stimuli_src_out.sync <= '0';
-- stimuli_data <= TO_SVEC( integer(round( c_sine_amplitude * sin(stimuli_count) )), g_data_w);
nxt_stimuli_src_out.data(g_data_w-1 DOWNTO 0) <= TO_SVEC( integer(round( c_sine_amplitude * sin(stimuli_count) )), g_data_w);
stimuli_count<=stimuli_count+c_sine_time_step;
WAIT FOR 5 ns;
END LOOP;
END LOOP;
END LOOP;
END IF;
-- Generate pseudo random noise
IF g_stimuli_mode="random" THEN
stimuli_src_out.valid <= '1';
nxt_stimuli_src_out.valid <= '1';
FOR I IN 0 TO g_nof_sync-1 LOOP
stimuli_data <= (OTHERS=>'0');
stimuli_src_out.sync <= '1'; -- cycle 0
nxt_stimuli_src_out.sync <= '1'; -- cycle 0
WAIT FOR 5 ns;
FOR j IN 1 TO g_nof_data_per_sync-1 LOOP
stimuli_src_out.sync <= '0';
nxt_stimuli_src_out.sync <= '0';
stimuli_data <= func_common_random(stimuli_data);
stimuli_src_out.data(g_data_w-1 DOWNTO 0) <= stimuli_data; --all g_nof_data_per_sync cycles
nxt_stimuli_src_out.data(g_data_w-1 DOWNTO 0) <= stimuli_data; --all g_nof_data_per_sync cycles
WAIT FOR 5 ns;
END LOOP;
END LOOP;
......@@ -222,7 +223,17 @@ BEGIN
tb_end <= '1';
WAIT;
END PROCESS;
p_stimuli_src_out: PROCESS(dp_rst, dp_clk) IS
BEGIN
IF dp_rst='1' THEN
stimuli_src_out <= c_dp_sosi_rst;
ELSIF RISING_EDGE(dp_clk) THEN
stimuli_src_out <= nxt_stimuli_src_out;
END IF;
END PROCESS;
-- nxt_stimuli_src_out.data(g_data_w-1 DOWNTO 0) <= stimuli_data;
----------------------------------------------------------------------------
-- st_histogram
......@@ -270,38 +281,26 @@ BEGIN
-- | 2 | 0 | 1 | Addr 2: 1024, others 0|
-- | 3 | 1 | 0 | Addr 3: 1024, others 0|
-- +-------------+-------------+----------+-----------------------+
----------------------------------------------------------------------------
-- Perform MM read and put result in ram_rd_word
p_verify_mm_read : PROCESS
BEGIN
st_histogram_ram_mosi.wr <= '0';
ram_rd_addr <= 0;
FOR i IN 0 TO g_nof_sync-1 LOOP
proc_common_wait_until_high(dp_clk, stimuli_src_out.sync);
proc_common_wait_some_cycles(dp_clk, 10);
FOR j IN 0 TO g_nof_bins-1 LOOP
proc_mem_mm_bus_rd(j, dp_clk, st_histogram_ram_mosi);
ram_rd_addr <= j;
ram_rd_word <= st_histogram_ram_miso.rddata(c_ram_dat_w-1 DOWNTO 0);
ram_rd_word_int <= TO_UINT(ram_rd_word);
END LOOP;
END LOOP;
WAIT;
END PROCESS;
-- Register st_histogram_ram_miso.rdval so we read only valid ram_rd_word
p_nxt_ram_rd_word_valid : PROCESS(dp_rst, dp_clk)
BEGIN
IF dp_rst = '1' THEN
ram_rd_word_valid <= '0';
prv_ram_rd_addr <= 0;
ELSIF RISING_EDGE(dp_clk) THEN
ram_rd_word_valid <= nxt_ram_rd_word_valid;
prv_ram_rd_addr <= ram_rd_addr; -- align the rd address with rd data for wave window debugging
END IF;
END PROCESS;
nxt_ram_rd_word_valid <= st_histogram_ram_miso.rdval;
-- Help signals that contain the histogram bins+data
histogram_bin_unsigned <= TO_UINT( prv_st_histogram_ram_mosi.address(c_ram_adr_w-1 DOWNTO 0));
histogram_bin_signed <= TO_SINT(offset_binary(prv_st_histogram_ram_mosi.address(c_ram_adr_w-1 DOWNTO 0)));
histogram_data <= TO_UINT(st_histogram_ram_miso.rddata(c_ram_dat_w-1 DOWNTO 0)) WHEN st_histogram_ram_miso.rdval='1'ELSE 0;
histogram_valid <= st_histogram_ram_miso.rdval;
-- Perform verification of ram_rd_word when ram_rd_word_valid
p_verify_assert : PROCESS
......@@ -311,31 +310,31 @@ BEGIN
sum_of_bins <= 0;
proc_common_wait_until_high(dp_clk, stimuli_src_out.sync);
FOR j IN 0 TO g_nof_bins-1 LOOP
proc_common_wait_until_high(dp_clk, ram_rd_word_valid);
proc_common_wait_until_high(dp_clk, histogram_valid);
IF i=0 THEN -- Sync period 0: we expect RAM to contain zeros
ASSERT ram_rd_word_int=0 REPORT "RAM contains wrong bin count (expected 0, actual " & INTEGER'IMAGE(ram_rd_word_int) & ")" SEVERITY ERROR;
ASSERT histogram_data=0 REPORT "RAM contains wrong bin count (expected 0, actual " & INTEGER'IMAGE(histogram_data) & ")" SEVERITY ERROR;
ELSE -- Sync period 1 onwards
IF g_stimuli_mode="counter" THEN
-- Counter data: ban values remain the same every sync
ASSERT ram_rd_word_int=c_expected_ram_content_counter REPORT "RAM contains wrong bin count (expected " & INTEGER'IMAGE(c_expected_ram_content_counter) & ", actual " & INTEGER'IMAGE(ram_rd_word_int) & ")" SEVERITY ERROR;
-- Counter data: bin values remain the same every sync
ASSERT histogram_data=c_expected_ram_content_counter REPORT "RAM contains wrong bin count (expected " & INTEGER'IMAGE(c_expected_ram_content_counter) & ", actual " & INTEGER'IMAGE(histogram_data) & ")" SEVERITY ERROR;
ELSIF g_stimuli_mode="dc" THEN
-- DC data: DC level increments every sync
IF j=(i/c_nof_levels_per_bin)+1 THEN -- Check bin address and account for multiple levels per bin
IF j=(i/c_nof_levels_per_bin) THEN -- Check bin address and account for multiple levels per bin
-- this address (j) should contain the DC level total count of this sync period (i)
ASSERT ram_rd_word_int=g_nof_data_per_sync REPORT "RAM contains wrong bin count (expected " & INTEGER'IMAGE(g_nof_data_per_sync) & ", actual " & INTEGER'IMAGE(ram_rd_word_int) & ")" SEVERITY ERROR;
ASSERT histogram_data=g_nof_data_per_sync REPORT "RAM contains wrong bin count (expected " & INTEGER'IMAGE(g_nof_data_per_sync) & ", actual " & INTEGER'IMAGE(histogram_data) & ")" SEVERITY ERROR;
ELSE
-- this address should contain zero
ASSERT ram_rd_word_int=0 REPORT "RAM contains wrong bin count (expected 0, actual " & INTEGER'IMAGE(ram_rd_word_int) & ")" SEVERITY ERROR;
ASSERT histogram_data=0 REPORT "RAM contains wrong bin count (expected 0, actual " & INTEGER'IMAGE(histogram_data) & ")" SEVERITY ERROR;
END IF;
END IF;
END IF;
sum_of_bins<=sum_of_bins+ram_rd_word_int; -- Keep the sum of all bins
WAIT FOR 5 ns;
sum_of_bins<=sum_of_bins+histogram_data; -- Keep the sum of all bins
WAIT FOR 5 ns;
END LOOP;
-- Check the sum of all bins
IF i>0 THEN -- Skip sync 0 (histogram still all zeros)
ASSERT sum_of_bins=g_nof_data_per_sync REPORT "Sum of bins not equal to g_nof_data_per_sync" SEVERITY ERROR;
ASSERT sum_of_bins=g_nof_data_per_sync REPORT "Sum of bins not equal to g_nof_data_per_sync (expected " & INTEGER'IMAGE(g_nof_data_per_sync) & ", actual " & INTEGER'IMAGE(sum_of_bins) & ")" SEVERITY ERROR;
END IF;
END LOOP;
......@@ -347,15 +346,19 @@ BEGIN
p_check_verification_done : PROCESS
BEGIN
proc_common_wait_until_high(dp_clk, stimuli_done);
proc_common_wait_some_cycles(dp_clk, 50);
ASSERT verification_done='1' REPORT "Verification failed" SEVERITY ERROR;
WAIT;
END PROCESS;
----------------------------------------------------------------------------
-- Create a signal that displays histogram (view as analog in Questa Sim)
-- in wave window
----------------------------------------------------------------------------
histogram <= ram_rd_word_int WHEN ram_rd_word_valid='1' ELSE 0;
-- Register MOSI to store the read address
p_clk: PROCESS(dp_rst, dp_clk) IS
BEGIN
IF dp_rst = '1' THEN
prv_st_histogram_ram_mosi <= c_mem_mosi_rst;
ELSIF RISING_EDGE(dp_clk) THEN
prv_st_histogram_ram_mosi <= st_histogram_ram_mosi;
END IF;
END PROCESS;
END tb;
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment