Skip to content
Snippets Groups Projects
Commit 486a166c authored by Reinier van der Walle's avatar Reinier van der Walle
Browse files

Merge branch 'L2SDP-840' into 'master'

Resolve L2SDP-840

Closes L2SDP-840

See merge request desp/hdl!285
parents 9e2d3015 32166ac5
Branches
No related tags found
1 merge request!285Resolve L2SDP-840
Pipeline #37621 passed
...@@ -442,6 +442,31 @@ peripherals: ...@@ -442,6 +442,31 @@ peripherals:
access_mode: RW access_mode: RW
- peripheral_name: dp_strobe_total_count
peripheral_description: "Count strobes"
parameters:
- { name: g_nof_counts_max, value: 15 } # fixed by REGMAP
- { name: g_nof_counts, value: 1 } # actual nof counts, <= g_nof_counts_max
mm_ports:
# MM port for dp_strobe_total_count.vhd
- mm_port_name: REG_DP_STROBE_TOTAL_COUNT
mm_port_type: REG
mm_port_span: ceil_pow2(g_nof_counts_max*2 + 1) * MM_BUS_SIZE
mm_port_description: ""
fields:
- - field_name: counts
field_description: "Total number of strobes counters."
number_of_fields: g_nof_counts
address_offset: 0
user_width: 64
radix: uint64
access_mode: RO
- - field_name: clear
field_description: "Read or write this register to clear all counters."
address_offset: (g_nof_counts_max*2 + 1) * MM_BUS_SIZE # 31 * MM_BUS_SIZE
access_mode: RW
- peripheral_name: dp_block_validate_err # pi_dp_block_validate_err.py - peripheral_name: dp_block_validate_err # pi_dp_block_validate_err.py
peripheral_description: "Validate the error field of a DP block" peripheral_description: "Validate the error field of a DP block"
parameters: parameters:
......
...@@ -63,6 +63,7 @@ synth_files = ...@@ -63,6 +63,7 @@ synth_files =
src/vhdl/dp_fifo_from_mm_reg.vhd src/vhdl/dp_fifo_from_mm_reg.vhd
src/vhdl/dp_fifo_monitor.vhd src/vhdl/dp_fifo_monitor.vhd
src/vhdl/dp_fifo_monitor_arr.vhd src/vhdl/dp_fifo_monitor_arr.vhd
src/vhdl/dp_strobe_total_count.vhd
src/vhdl/dp_block_validate_err.vhd src/vhdl/dp_block_validate_err.vhd
src/vhdl/mms_dp_fifo_to_mm.vhd src/vhdl/mms_dp_fifo_to_mm.vhd
src/vhdl/mms_dp_fifo_from_mm.vhd src/vhdl/mms_dp_fifo_from_mm.vhd
...@@ -186,8 +187,6 @@ synth_files = ...@@ -186,8 +187,6 @@ synth_files =
src/vhdl/dp_selector.vhd src/vhdl/dp_selector.vhd
src/vhdl/mms_dp_scale.vhd src/vhdl/mms_dp_scale.vhd
tb/vhdl/dp_stream_player.vhd tb/vhdl/dp_stream_player.vhd
tb/vhdl/dp_sosi_recorder.vhd tb/vhdl/dp_sosi_recorder.vhd
tb/vhdl/dp_stream_rec_play.vhd tb/vhdl/dp_stream_rec_play.vhd
...@@ -201,6 +200,7 @@ test_bench_files = ...@@ -201,6 +200,7 @@ test_bench_files =
tb/vhdl/dp_stream_stimuli.vhd tb/vhdl/dp_stream_stimuli.vhd
tb/vhdl/dp_stream_verify.vhd tb/vhdl/dp_stream_verify.vhd
tb/vhdl/tb_dp_strobe_total_count.vhd
tb/vhdl/tb_dp_block_select.vhd tb/vhdl/tb_dp_block_select.vhd
tb/vhdl/tb_dp_block_validate_length.vhd tb/vhdl/tb_dp_block_validate_length.vhd
tb/vhdl/tb_dp_block_validate_err.vhd tb/vhdl/tb_dp_block_validate_err.vhd
...@@ -287,7 +287,7 @@ test_bench_files = ...@@ -287,7 +287,7 @@ test_bench_files =
tb/vhdl/tb_mms_dp_gain_arr.vhd tb/vhdl/tb_mms_dp_gain_arr.vhd
tb/vhdl/tb_mms_dp_gain_serial_arr.vhd tb/vhdl/tb_mms_dp_gain_serial_arr.vhd
tb/vhdl/tb_tb_dp_strobe_total_count.vhd
tb/vhdl/tb_tb_dp_block_select.vhd tb/vhdl/tb_tb_dp_block_select.vhd
tb/vhdl/tb_tb_dp_block_validate_length.vhd tb/vhdl/tb_tb_dp_block_validate_length.vhd
tb/vhdl/tb_tb_dp_block_validate_err.vhd tb/vhdl/tb_tb_dp_block_validate_err.vhd
......
...@@ -261,7 +261,7 @@ BEGIN ...@@ -261,7 +261,7 @@ BEGIN
count_reg((g_nof_err_counts+1) * c_word_w - 1 DOWNTO g_nof_err_counts * c_word_w ) <= RESIZE_UVEC(hold_cnt_discarded, c_word_w); count_reg((g_nof_err_counts+1) * c_word_w - 1 DOWNTO g_nof_err_counts * c_word_w ) <= RESIZE_UVEC(hold_cnt_discarded, c_word_w);
gen_blk_cnt_32b : IF g_blk_cnt_w < c_word_w GENERATE gen_blk_cnt_32b : IF g_blk_cnt_w <= c_word_w GENERATE
count_reg((g_nof_err_counts+2) * c_word_w - 1 DOWNTO (g_nof_err_counts+1) * c_word_w ) <= RESIZE_UVEC(hold_cnt_blk, c_word_w); -- low part count_reg((g_nof_err_counts+2) * c_word_w - 1 DOWNTO (g_nof_err_counts+1) * c_word_w ) <= RESIZE_UVEC(hold_cnt_blk, c_word_w); -- low part
count_reg((g_nof_err_counts+3) * c_word_w - 1 DOWNTO (g_nof_err_counts+2) * c_word_w ) <= (OTHERS=>'0'); -- high part (not used) count_reg((g_nof_err_counts+3) * c_word_w - 1 DOWNTO (g_nof_err_counts+2) * c_word_w ) <= (OTHERS=>'0'); -- high part (not used)
END GENERATE; END GENERATE;
......
-------------------------------------------------------------------------------
--
-- Copyright 2022
-- 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: E. Kooistra
-- Purpose:
-- Count strobes
-- Description:
-- * g_nof_counts >= 1, maximum g_nof_counts_max = 15
-- There are g_nof_counts in parallel, one clear that clears them all
-- . count any strobe like e.g. sync, sop, valid, error flag, ...
-- . MM read or write of clear registers clears all counter immediately,
-- the clear data value is dont care.
-- . the count clips at 2**g_count_w-1 in case of overflow when g_clip =
-- TRUE, else it wraps and continues from 0.
-- * g_count_w <= 64
-- Internally the counts have width g_count_w <= 64, on the MM interface
-- all counts use 2 words, so 64 bits.
-- * ref_sync:
-- . Enable or re-enable count starts at a ref_sync.
-- . MM read of a count shows the strobe count that is captured at a ref_sync
-- (default input ref_sync = '1' when not used)
-- * g_mm_w = c_word_w
-- Default use g_mm_w = 32b for MM, but support < 32 to ease verification of
-- count values > 2**g_mm_w.
--
-------------------------------------------------------------------------------
-- REGMAP
-- . address span is (g_nof_counts_max + 1)*2 = 32
-------------------------------------------------------------------------------
-- wi Bits R/W Name Default
-- ===========================================================================
-- 0 [31..0] RO count[0] 0x0
-- 1 [63.32]
-- 2 [31..0] RO count[1] 0x0
-- 3 [63.32]
-- . . . . .
-- . .
-- (g_nof_counts-1)*2 [31..0] RO count[g_nof_counts-1] 0x0
-- (g_nof_counts-1)*2 + 1 [63.32]
-- . . . . .
-- . .
-- (g_nof_counts_max-1)*2 [31..0] RO count[g_nof_counts_max-1] 0x0
-- (g_nof_counts_max-1)*2 + 1 [63.32]
-- g_nof_counts_max*2 [31..0] RW clear 0x0
-- g_nof_counts_max*2 + 1 [31..0] RO rsvd 0x0
-- ===========================================================================
--
LIBRARY IEEE, common_lib;
USE IEEE.std_logic_1164.all;
USE IEEE.numeric_std.all;
USE common_lib.common_pkg.ALL;
USE common_lib.common_mem_pkg.ALL;
ENTITY dp_strobe_total_count IS
GENERIC (
g_mm_w : NATURAL := c_word_w;
g_nof_counts_max : NATURAL := 15; -- fixed by REGMAP
g_nof_counts : NATURAL := 1; -- actual nof counts, <= g_nof_counts_max
g_count_w : NATURAL := c_longword_w; -- actual count width, max is c_longword_w due to two mm word width
g_clip : BOOLEAN := TRUE
);
PORT (
dp_rst : IN STD_LOGIC;
dp_clk : IN STD_LOGIC;
ref_sync : IN STD_LOGIC := '1';
in_strobe_arr : IN STD_LOGIC_VECTOR(g_nof_counts-1 DOWNTO 0);
mm_rst : IN STD_LOGIC;
mm_clk : IN STD_LOGIC;
reg_mosi : IN t_mem_mosi := c_mem_mosi_rst;
reg_miso : OUT t_mem_miso
);
END dp_strobe_total_count;
ARCHITECTURE rtl OF dp_strobe_total_count IS
CONSTANT c_nof_words : NATURAL := g_nof_counts_max*2 + 1; -- +1 for clear
CONSTANT c_clear_adr : NATURAL := g_nof_counts_max*2; -- after counters in REGMAP
-- Define the size of the MM slave register
CONSTANT c_mm_reg : t_c_mem := (latency => 1,
adr_w => ceil_log2(c_nof_words),
dat_w => g_mm_w, -- Use MM bus data width = c_word_w = 32 for all MM registers
nof_dat => c_nof_words,
init_sl => '0');
TYPE t_cnt_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(g_count_w-1 DOWNTO 0);
-- Registers in dp_clk domain
SIGNAL ref_sync_reg : STD_LOGIC := '0';
SIGNAL in_strobe_reg_arr : STD_LOGIC_VECTOR(g_nof_counts-1 DOWNTO 0) := (OTHERS=>'0');
SIGNAL rd_reg : STD_LOGIC_VECTOR(c_mm_reg.nof_dat*c_mm_reg.dat_w-1 DOWNTO 0) := (OTHERS=>'0');
SIGNAL mm_cnt_clr : STD_LOGIC;
SIGNAL cnt_clr : STD_LOGIC;
SIGNAL cnt_en : STD_LOGIC := '0';
SIGNAL cnt_en_arr : STD_LOGIC_VECTOR(g_nof_counts-1 DOWNTO 0);
SIGNAL cnt_arr : t_cnt_arr(g_nof_counts-1 DOWNTO 0);
SIGNAL hold_cnt_arr : t_cnt_arr(g_nof_counts-1 DOWNTO 0) := (OTHERS=>(OTHERS=>'0'));
BEGIN
ASSERT g_nof_counts <= g_nof_counts_max REPORT "Too many counters to fit REGMAP." SEVERITY FAILURE;
ASSERT g_count_w <= g_mm_w*2 REPORT "Too wide counter to fit REGMAP." SEVERITY FAILURE;
mm_cnt_clr <= (reg_mosi.rd OR reg_mosi.wr) WHEN TO_UINT(reg_mosi.address(c_mm_reg.adr_w-1 DOWNTO 0)) = c_clear_adr ELSE '0' ;
u_common_spulse : ENTITY common_lib.common_spulse
PORT MAP (
in_rst => mm_rst,
in_clk => mm_clk,
in_pulse => mm_cnt_clr,
out_rst => dp_rst,
out_clk => dp_clk,
out_pulse => cnt_clr
);
-- . register ref_sync to ease timing closure for ref_sync fanout
ref_sync_reg <= ref_sync WHEN rising_edge(dp_clk);
-- . register in_strobe_arr to preserve alignment with ref_sync
in_strobe_reg_arr <= in_strobe_arr WHEN rising_edge(dp_clk);
-- . clear strobe counters immediately at cnt_clr
-- . start strobe counters after ref_sync, e.g. to align strobe counters in different nodes in
-- case the input was (already) active during the cnt_clr
cnt_en <= '0' WHEN cnt_clr = '1' ELSE '1' WHEN ref_sync_reg = '1' ELSE cnt_en;
-- strobe counters
gen_counters : FOR I IN 0 TO g_nof_counts-1 GENERATE
cnt_en_arr(I) <= cnt_en AND in_strobe_reg_arr(I);
u_counter : ENTITY common_lib.common_counter
GENERIC MAP (
g_width => g_count_w,
g_clip => g_clip
)
PORT MAP (
rst => dp_rst,
clk => dp_clk,
cnt_clr => cnt_clr,
cnt_en => cnt_en_arr(I),
count => cnt_arr(I)
);
END GENERATE;
-- Hold counter values at ref_sync_reg to have stable values for MM read for comparision between nodes
p_hold_counters : PROCESS(dp_clk)
BEGIN
IF rising_edge(dp_clk) THEN
IF cnt_clr = '1' THEN
hold_cnt_arr <= (OTHERS=>(OTHERS=>'0'));
ELSIF ref_sync_reg = '1' THEN
hold_cnt_arr <= cnt_arr;
END IF;
END IF;
END PROCESS;
-- Register mapping
gen_cnt : FOR I IN 0 TO g_nof_counts-1 GENERATE
gen_reg_32b : IF g_count_w <= g_mm_w GENERATE
rd_reg((2*I + 1) * g_mm_w - 1 DOWNTO (2*I + 0) * g_mm_w) <= RESIZE_UVEC(hold_cnt_arr(I), g_mm_w); -- low part
rd_reg((2*I + 2) * g_mm_w - 1 DOWNTO (2*I + 1) * g_mm_w) <= (OTHERS=>'0'); -- high part (not used)
END GENERATE;
gen_reg_64b : IF g_count_w > g_mm_w GENERATE
rd_reg((2*I + 1) * g_mm_w - 1 DOWNTO (2*I + 0) * g_mm_w) <= hold_cnt_arr(I)(g_mm_w-1 DOWNTO 0); -- low part
rd_reg((2*I + 2) * g_mm_w - 1 DOWNTO (2*I + 1) * g_mm_w) <= RESIZE_UVEC(hold_cnt_arr(I)(g_count_w-1 DOWNTO g_mm_w), g_mm_w); -- high part
END GENERATE;
END GENERATE;
u_reg : ENTITY common_lib.common_reg_r_w_dc
GENERIC MAP (
g_cross_clock_domain => TRUE,
g_readback => FALSE,
g_reg => c_mm_reg
)
PORT MAP (
-- Clocks and reset
mm_rst => mm_rst,
mm_clk => mm_clk,
st_rst => dp_rst,
st_clk => dp_clk,
-- Memory Mapped Slave in mm_clk domain
sla_in => reg_mosi,
sla_out => reg_miso,
-- MM registers in st_clk domain
reg_wr_arr => OPEN,
reg_rd_arr => OPEN,
in_reg => rd_reg, -- read only
out_reg => OPEN -- no write
);
END rtl;
...@@ -86,14 +86,14 @@ ARCHITECTURE tb OF tb_dp_block_validate_err IS ...@@ -86,14 +86,14 @@ ARCHITECTURE tb OF tb_dp_block_validate_err IS
SIGNAL stimuli_end : STD_LOGIC; SIGNAL stimuli_end : STD_LOGIC;
SIGNAL stimuli_sosi : t_dp_sosi; SIGNAL stimuli_sosi : t_dp_sosi;
SIGNAL stimuli_siso : t_dp_siso; SIGNAL stimuli_siso : t_dp_siso;
SIGNAL stimuli_cnt_reg : NATURAL;
SIGNAL stimuli_cnt : NATURAL;
SIGNAL verify_sosi : t_dp_sosi; SIGNAL verify_sosi : t_dp_sosi;
SIGNAL verify_siso : t_dp_siso := c_dp_siso_rdy; SIGNAL verify_siso : t_dp_siso := c_dp_siso_rdy;
SIGNAL reference_cnt : NATURAL; SIGNAL reference_cnt : NATURAL;
SIGNAL reference_cnt_reg : NATURAL; SIGNAL reference_cnt_reg : NATURAL;
SIGNAL reference_sosi : t_dp_sosi; SIGNAL reference_sosi : t_dp_sosi;
SIGNAL reference_siso : t_dp_siso := c_dp_siso_rdy; SIGNAL reference_siso : t_dp_siso := c_dp_siso_rdy;
SIGNAL reg_mosi : t_mem_mosi := c_mem_mosi_rst; SIGNAL reg_mosi : t_mem_mosi := c_mem_mosi_rst;
SIGNAL reg_miso : t_mem_miso := c_mem_miso_rst; SIGNAL reg_miso : t_mem_miso := c_mem_miso_rst;
......
-------------------------------------------------------------------------------
--
-- Copyright 2022
-- 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: E. Kooistra
-- Purpose: Test bench for dp_strobe_total_count.vhd
-- Description:
-- * maximum g_count_w = 31 to fit in largest NATURAL
-- * Use g_mm_w < c_word_w = 32 to simulate large counts in feasible time.
-- * Use g_nof_sync in combination with g_mm_w and g_count_w to achieve
-- . a count > 2**g_mm_w that uses the high part of an MM word
-- . a count > 2**(g_mm_w*2) that will clip at 2**g_mm_w - 1
-- Usage:
-- . as 5
-- . run -all
LIBRARY IEEE, common_lib;
USE IEEE.std_logic_1164.ALL;
USE IEEE.numeric_std.ALL;
USE common_lib.common_pkg.ALL;
USE common_lib.common_mem_pkg.ALL;
USE common_lib.tb_common_mem_pkg.ALL;
USE common_lib.common_str_pkg.ALL;
USE common_lib.tb_common_pkg.ALL;
USE work.dp_stream_pkg.ALL;
ENTITY tb_dp_strobe_total_count IS
GENERIC (
g_mm_w : NATURAL := 8;
g_count_w : NATURAL := 7;
g_nof_blocks_per_sync : NATURAL := 10;
g_nof_valid_per_blk : NATURAL := 10;
g_nof_sync : NATURAL := 10;
g_gap_size : NATURAL := 3
);
END tb_dp_strobe_total_count;
ARCHITECTURE tb OF tb_dp_strobe_total_count IS
------------------------------------------------------------------------------
-- Clock & reset
------------------------------------------------------------------------------
CONSTANT c_dp_clk_period : TIME := 5 ns;
CONSTANT c_mm_clk_period : TIME := 10 ns;
CONSTANT c_skip_nof_sync : NATURAL := 3;
CONSTANT c_tb_nof_sync : NATURAL := c_skip_nof_sync + g_nof_sync;
CONSTANT c_clip : BOOLEAN := TRUE;
-- dut
CONSTANT c_nof_counts_max : NATURAL := 15;
CONSTANT c_nof_counts : NATURAL := 3; -- count stimuli.sync, sop, valid
CONSTANT c_count_max : NATURAL := 2**g_count_w - 1;
CONSTANT c_mm_addr_clear : NATURAL := c_nof_counts_max*2;
-- c_tb_nof_sync - c_skip_nof_sync because first sync intervals are skipped
-- by using clear, and -1, because stimuli_sosi.sync is used as ref_sync,
-- and ref_sync is used to hold the counts.
CONSTANT c_exp_nof_sync : NATURAL := c_tb_nof_sync - c_skip_nof_sync - 1;
CONSTANT c_nof_blk : NATURAL := g_nof_blocks_per_sync * c_exp_nof_sync;
CONSTANT c_exp_nof_sop : NATURAL := sel_a_b(c_nof_blk < c_count_max, c_nof_blk, c_count_max);
CONSTANT c_nof_valid : NATURAL := c_nof_blk * g_nof_valid_per_blk;
CONSTANT c_exp_nof_valid : NATURAL := sel_a_b(c_nof_valid < c_count_max, c_nof_valid, c_count_max);
SIGNAL dp_clk : STD_LOGIC := '1';
SIGNAL mm_clk : STD_LOGIC := '1';
SIGNAL rst : STD_LOGIC := '1';
SIGNAL tb_end : STD_LOGIC := '0';
SIGNAL stimuli_rst : STD_LOGIC := '1';
SIGNAL stimuli_end : STD_LOGIC;
SIGNAL stimuli_sosi : t_dp_sosi;
SIGNAL stimuli_strobe_arr : STD_LOGIC_VECTOR(c_nof_counts-1 DOWNTO 0);
SIGNAL reg_mosi : t_mem_mosi := c_mem_mosi_rst;
SIGNAL reg_miso : t_mem_miso := c_mem_miso_rst;
SIGNAL rd_count_arr : t_natural_arr(c_nof_counts-1 DOWNTO 0);
SIGNAL exp_count_arr : t_natural_arr(c_nof_counts-1 DOWNTO 0) := (c_exp_nof_valid, c_exp_nof_sop, c_exp_nof_sync);
BEGIN
------------------------------------------------------------------------------
-- Clock & reset
------------------------------------------------------------------------------
dp_clk <= (NOT dp_clk) OR tb_end AFTER c_dp_clk_period/2;
mm_clk <= (NOT mm_clk) OR tb_end AFTER c_mm_clk_period/2;
rst <= '1', '0' AFTER c_dp_clk_period*7;
------------------------------------------------------------------------------
-- Stimuli:
------------------------------------------------------------------------------
stimuli_rst <= '1', '0' AFTER c_dp_clk_period*17;
-- Generate snk_in with data frames
u_stimuli : ENTITY work.dp_stream_stimuli
GENERIC MAP (
g_sync_period => g_nof_blocks_per_sync,
g_nof_repeat => g_nof_blocks_per_sync * c_tb_nof_sync,
g_pkt_len => g_nof_valid_per_blk,
g_pkt_gap => g_gap_size
)
PORT MAP (
rst => stimuli_rst,
clk => dp_clk,
-- Generate stimuli
src_out => stimuli_sosi,
-- End of stimuli
tb_end => stimuli_end
);
stimuli_strobe_arr(0) <= stimuli_sosi.sync;
stimuli_strobe_arr(1) <= stimuli_sosi.sop;
stimuli_strobe_arr(2) <= stimuli_sosi.valid;
------------------------------------------------------------------------------
-- DUT
------------------------------------------------------------------------------
u_dut : ENTITY work.dp_strobe_total_count
GENERIC MAP (
g_mm_w => g_mm_w,
g_nof_counts_max => c_nof_counts_max,
g_nof_counts => c_nof_counts,
g_count_w => g_count_w,
g_clip => c_clip
)
PORT MAP (
dp_rst => rst,
dp_clk => dp_clk,
ref_sync => stimuli_sosi.sync,
in_strobe_arr => stimuli_strobe_arr,
mm_rst => rst,
mm_clk => mm_clk,
reg_mosi => reg_mosi,
reg_miso => reg_miso
);
------------------------------------------------------------------------------
-- Verification
------------------------------------------------------------------------------
p_mm : PROCESS
VARIABLE v_rd_data : STD_LOGIC_VECTOR(g_mm_w-1 DOWNTO 0);
VARIABLE v_rd_count : NATURAL;
BEGIN
-- Wait until strobes have started, skip first sync intervals
FOR I IN 0 TO c_skip_nof_sync-1 LOOP
proc_common_wait_until_lo_hi(dp_clk, stimuli_sosi.sync);
END LOOP;
proc_common_wait_some_cycles(dp_clk, 1);
-- Clear to restart counting at next sync interval
proc_mem_mm_bus_wr(c_mm_addr_clear, 1, mm_clk, reg_mosi);
proc_common_wait_until_lo_hi(dp_clk, stimuli_end);
proc_common_wait_some_cycles(dp_clk, 10);
proc_common_wait_some_cycles(mm_clk, 1);
FOR I IN 0 TO c_nof_counts-1 LOOP
-- read low part
proc_mem_mm_bus_rd(I*2, mm_clk, reg_miso, reg_mosi);
proc_mem_mm_bus_rd_latency(1, mm_clk);
v_rd_data := reg_miso.rddata(g_mm_w-1 DOWNTO 0);
v_rd_count := TO_UINT(v_rd_data);
-- read and add high part
proc_mem_mm_bus_rd(I*2+1, mm_clk, reg_miso, reg_mosi);
proc_mem_mm_bus_rd_latency(1, mm_clk);
v_rd_data := reg_miso.rddata(g_mm_w-1 DOWNTO 0);
v_rd_count := v_rd_count + TO_UINT(v_rd_data) * 2**g_mm_w;
rd_count_arr(I) <= v_rd_count;
ASSERT exp_count_arr(I) = v_rd_count REPORT "Wrong total block count(" & NATURAL'IMAGE(I) & ")" SEVERITY ERROR;
END LOOP;
proc_common_wait_some_cycles(dp_clk, 100);
tb_end <= '1';
WAIT;
END PROCESS;
END tb;
-------------------------------------------------------------------------------
--
-- Copyright 2022
-- 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: E. Kooistra
-- Purpose: Verify multiple variations of tb_dp_strobe_total_count
-- Usage:
-- > as 3
-- > run -all
LIBRARY IEEE;
USE IEEE.std_logic_1164.ALL;
ENTITY tb_tb_dp_strobe_total_count IS
END tb_tb_dp_strobe_total_count;
ARCHITECTURE tb OF tb_tb_dp_strobe_total_count IS
SIGNAL tb_end : STD_LOGIC := '0'; -- declare tb_end to avoid 'No objects found' error on 'when -label tb_end'
BEGIN
--g_mm_w : NATURAL := c_word_w;
--g_count_w : NATURAL := 16;
--g_nof_blocks_per_sync : NATURAL := 10;
--g_nof_valid_per_blk : NATURAL := 10;
--g_nof_sync : NATURAL := 10;
--g_gap_size : NATURAL := 0;
-- Use g_nof_blocks_per_sync * g_nof_valid_per_blk = 100 valid per sync and
-- use g_nof_sync = 10, so maximum expected valid count is 900.
-- Maximum expected sop count is 90
-- Maximum expected sync count is 9
-- Default usage
u_mm32b_cnt16b_no_gap : ENTITY work.tb_dp_strobe_total_count GENERIC MAP(32, 16, 10,10, 10, 0);
u_mm32b_cnt16b_gap : ENTITY work.tb_dp_strobe_total_count GENERIC MAP(32, 16, 10,10, 10, 3);
-- Check MM high word and counter overflow (clipping)
u_mm8b_cnt16b_high : ENTITY work.tb_dp_strobe_total_count GENERIC MAP(8, 16, 10,10, 10, 3); -- use high part
u_mm8b_cnt9b_overflow : ENTITY work.tb_dp_strobe_total_count GENERIC MAP(8, 9, 10,10, 10, 3); -- cause overflow to clip count high part
u_mm8b_cnt7b_overflow : ENTITY work.tb_dp_strobe_total_count GENERIC MAP(8, 7, 10,10, 10, 3); -- cause overflow to clip count low part
END tb;
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment