diff --git a/libraries/base/diag/hdllib.cfg b/libraries/base/diag/hdllib.cfg index 10d51293521cf0bbf384b5461308ba2af5a3719a..e1dd075816a3c6d3c67197fcd4be47e3821e62a4 100644 --- a/libraries/base/diag/hdllib.cfg +++ b/libraries/base/diag/hdllib.cfg @@ -34,7 +34,7 @@ test_bench_files = $UNB/Firmware/modules/Lofar/diag/tb/vhdl/tb_diag_wg_wideband.vhd $UNB/Firmware/modules/Lofar/diag/tb/vhdl/tb_diag_tx_seq.vhd $UNB/Firmware/modules/Lofar/diag/tb/vhdl/tb_diag_rx_seq.vhd - $UNB/Firmware/modules/Lofar/diag/tb/vhdl/tb_diag_tx_frm.vhd + tb/vhdl/tb_diag_tx_frm.vhd $UNB/Firmware/modules/Lofar/diag/tb/vhdl/tb_diag_frm_generator.vhd $UNB/Firmware/modules/Lofar/diag/tb/vhdl/tb_diag_frm_monitor.vhd tb/vhdl/tb_mms_diag_seq.vhd diff --git a/libraries/base/diag/tb/vhdl/tb_diag_tx_frm.vhd b/libraries/base/diag/tb/vhdl/tb_diag_tx_frm.vhd new file mode 100644 index 0000000000000000000000000000000000000000..9af57b3ee0549937bb388cf4cc1e269ad99c9670 --- /dev/null +++ b/libraries/base/diag/tb/vhdl/tb_diag_tx_frm.vhd @@ -0,0 +1,202 @@ +-------------------------------------------------------------------------------- +-- +-- Copyright (C) 2009 +-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/> +-- JIVE (Joint Institute for VLBI in Europe) <http://www.jive.nl/> +-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands +-- +-- This program is free software: you can redistribute it and/or modify +-- it under the terms of the GNU General Public License as published by +-- the Free Software Foundation, either version 3 of the License, or +-- (at your option) any later version. +-- +-- This program is distributed in the hope that it will be useful, +-- but WITHOUT ANY WARRANTY; without even the implied warranty of +-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +-- GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License +-- along with this program. If not, see <http://www.gnu.org/licenses/>. +-- +-------------------------------------------------------------------------------- + +LIBRARY IEEE, common_lib; +USE IEEE.STD_LOGIC_1164.ALL; +USE IEEE.NUMERIC_STD.ALL; +USE common_lib.common_pkg.ALL; + +ENTITY tb_diag_tx_frm IS +END tb_diag_tx_frm; + +ARCHITECTURE tb OF tb_diag_tx_frm IS + + CONSTANT c_period : TIME := 100 ns; + CONSTANT c_nof_cycles : NATURAL := 83; -- use prime number to avoid periodicity with sequence data, which can confuse interpretating the data + + CONSTANT c_sel : STD_LOGIC := '1'; -- select COUNTER sequence + CONSTANT c_init : NATURAL := 2; -- test sequence init value + CONSTANT c_frame_len : NATURAL := 20; -- >= 2, test frame length + CONSTANT c_frame_len_w : NATURAL := ceil_log2(c_frame_len); + CONSTANT c_dat_w : NATURAL := c_frame_len_w; + + SIGNAL rst : STD_LOGIC; + SIGNAL clk : STD_LOGIC := '1'; + + SIGNAL diag_sel : STD_LOGIC; + SIGNAL diag_frame_len : STD_LOGIC_VECTOR(c_frame_len_w-1 DOWNTO 0) := TO_UVEC(c_frame_len, c_frame_len_w); + SIGNAL diag_dat : STD_LOGIC_VECTOR(c_dat_w-1 DOWNTO 0); + SIGNAL diag_ready : STD_LOGIC; + SIGNAL diag_sop : STD_LOGIC; + + SIGNAL seq_req : STD_LOGIC; + SIGNAL seq_dat : STD_LOGIC_VECTOR(c_dat_w-1 DOWNTO 0); + SIGNAL prev_seq_dat : STD_LOGIC_VECTOR(c_dat_w-1 DOWNTO 0) := TO_UVEC(c_init+c_frame_len-1, c_dat_w); + SIGNAL seq_val : STD_LOGIC; + SIGNAL seq_sop : STD_LOGIC; + SIGNAL seq_eop : STD_LOGIC; + +BEGIN + + rst <= '1', '0' AFTER c_period/10; + clk <= NOT clk AFTER c_period/2; + + stimuli: PROCESS + -- run 100 us + BEGIN + diag_sel <= c_sel; + diag_dat <= TO_UVEC(c_init, c_dat_w); + diag_sop <= '0'; + seq_req <= '1'; + WAIT FOR 10*c_period; + + -- Keep seq_req='1' + seq_req <= '1'; + WAIT FOR c_period; + diag_sop <= '1'; -- Generate one frame + WAIT FOR c_period; + diag_sop <= '0'; + WAIT FOR c_nof_cycles*c_period; + WAIT FOR 10*c_period; + + -- Keep seq_req='1' + seq_req <= '1'; + diag_dat <= TO_UVEC(0, c_dat_w); + WAIT FOR 10*c_period; + diag_sop <= '1'; -- Generate one frame with actual c_init only during diag_sop + diag_dat <= TO_UVEC(c_init, c_dat_w); + WAIT FOR c_period; + diag_sop <= '0'; + diag_dat <= TO_UVEC(0, c_dat_w); + WAIT FOR c_nof_cycles*c_period; + WAIT FOR 10*c_period; + diag_dat <= TO_UVEC(c_init, c_dat_w); + + -- Keep diag_sop='1' to immediately request a next frame again + seq_req <= '1'; + diag_sop <= '1'; -- Immediatly generate a frame when generator indicates ready + FOR I IN 0 TO 3*c_frame_len LOOP + WAIT FOR c_period; + END LOOP; + diag_sop <= '0'; + WAIT FOR c_frame_len*c_period; + WAIT FOR 10*c_period; + + -- Use diag_ready to immediately request a next frame again + seq_req <= '1'; + FOR I IN 0 TO 3*c_frame_len LOOP + diag_sop <= diag_ready; -- Immediatly generate a frame when generator indicates ready + WAIT FOR c_period; + END LOOP; + diag_sop <= '0'; + WAIT FOR c_frame_len*c_period; + WAIT FOR 10*c_period; + + -- Toggle seq_req='1' + seq_req <= '1'; + WAIT FOR c_period; + diag_sop <= '1'; -- Generate one frame + WAIT FOR c_period; + diag_sop <= '0'; + WAIT FOR 10*c_period; + seq_req <= '0'; -- One inactive request cycle + WAIT FOR c_period; + seq_req <= '1'; + WAIT FOR c_nof_cycles*c_period; + WAIT FOR 10*c_period; + + -- Make seq_req='0' near end of frame + seq_req <= '1'; + WAIT FOR c_period; + diag_sop <= '1'; -- Generate one frame + WAIT FOR c_period; + diag_sop <= '0'; + WAIT FOR (c_frame_len-1)*c_period; + seq_req <= '0'; -- Some inactive request cycles + WAIT FOR 5*c_period; + seq_req <= '1'; + WAIT FOR c_nof_cycles*c_period; + WAIT FOR 10*c_period; + + -- Keep diag_sop='1' and make seq_req='0' near end of frame + seq_req <= '1'; + WAIT FOR c_period; + diag_sop <= '1'; -- Generate one frame + WAIT FOR c_period; + diag_sop <= '1'; + WAIT FOR (c_frame_len-1)*c_period; + seq_req <= '0'; -- Some inactive request cycles + WAIT FOR 5*c_period; + seq_req <= '1'; + WAIT FOR 5*c_period; + diag_sop <= '0'; + WAIT FOR c_nof_cycles*c_period; + WAIT FOR 10*c_period; + + WAIT; + END PROCESS; + + u_diag_tx_frm : ENTITY work.diag_tx_frm + GENERIC MAP ( + g_sel => c_sel, + g_init => c_init, + g_frame_len => c_frame_len, + g_dat_w => c_dat_w + ) + PORT MAP ( + rst => rst, + clk => clk, + clken => '1', + -- Static control input (connect via MM or leave open to use default) + diag_sel => diag_sel, + diag_frame_len => diag_frame_len, + -- Dynamic control input (connect via MM or via ST input or leave open to use defaults) + diag_ready => diag_ready, + diag_dat => diag_dat, + diag_sop => diag_sop, + -- ST output + out_ready => seq_req, + out_dat => seq_dat, + out_val => seq_val, + out_sop => seq_sop, + out_eop => seq_eop + ); + + + prev_seq_dat <= seq_dat WHEN rising_edge(clk) AND seq_val='1'; + + p_verify : PROCESS(clk) + BEGIN + IF rising_edge(clk) THEN + IF seq_sop='1' THEN ASSERT seq_val='1' AND UNSIGNED(seq_dat)=c_init REPORT "Unexpected seq_sop"; END IF; + IF seq_eop='1' THEN ASSERT seq_val='1' AND UNSIGNED(seq_dat)=c_init+c_frame_len-1 REPORT "Unexpected seq_eop"; END IF; + + IF seq_val='1' AND UNSIGNED(seq_dat)=c_init THEN ASSERT seq_sop='1' REPORT "Missing seq_sop"; END IF; + IF seq_val='1' AND UNSIGNED(seq_dat)=c_init+c_frame_len-1 THEN ASSERT seq_eop='1' REPORT "Missing seq_eop"; END IF; + + IF seq_val='1' AND UNSIGNED(seq_dat)=c_init THEN ASSERT UNSIGNED(prev_seq_dat)=c_init+c_frame_len-1 REPORT "Wrong last seq_dat"; END IF; + IF seq_val='1' AND UNSIGNED(seq_dat)>c_init THEN ASSERT UNSIGNED(prev_seq_dat)= UNSIGNED(seq_dat)-1 REPORT "Wrong seq_dat"; END IF; + END IF; + END PROCESS; + +END tb; +