From f03dac9c5b66f0ea215b13004eb86096c3b552d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Franti=C5=A1ek=20Boh=C3=A1=C4=8Dek?= Date: Wed, 15 Mar 2023 17:20:07 +0100 Subject: [PATCH] feat(tests): add tests for jesd204b_rx toplevel entity --- testbench/jesd204b_rx_data_tb.vhd | 199 ++++++++++++++++++++++++++++ testbench/jesd204b_rx_ils_tb.vhd | 195 +++++++++++++++++++++++++++ testbench/jesd204b_rx_kchars_tb.vhd | 132 ++++++++++++++++++ 3 files changed, 526 insertions(+) create mode 100644 testbench/jesd204b_rx_data_tb.vhd create mode 100644 testbench/jesd204b_rx_ils_tb.vhd create mode 100644 testbench/jesd204b_rx_kchars_tb.vhd diff --git a/testbench/jesd204b_rx_data_tb.vhd b/testbench/jesd204b_rx_data_tb.vhd new file mode 100644 index 0000000..2009ad0 --- /dev/null +++ b/testbench/jesd204b_rx_data_tb.vhd @@ -0,0 +1,199 @@ +library ieee; +use ieee.std_logic_1164.all; +use work.testing_functions.all; +use work.jesd204b_pkg.all; +use work.data_link_pkg.all; +use work.transport_pkg.all; + +entity jesd204b_rx_data_tb is +end entity jesd204b_rx_data_tb; + +architecture a1 of jesd204b_rx_data_tb is + constant K : integer := 9; + constant CS : integer := 2; + constant M : integer := 2; -- Count of converters + constant S : integer := 1; -- Count of samples + constant L : integer := 2; -- Count of lanes + constant F : integer := 2; -- Count of octets in a frame per lane + constant CF : integer := 0; -- Count of control word bits + constant N : integer := 14; -- Sample size + constant Nn : integer := 16; + + type octet_data is record + data : std_logic_vector(7 downto 0); + k : std_logic; + end record octet_data; + + type lane_data_array is array (natural range <>) of octet_data; + type test_vector is record + data : lane_data_array(0 to L-1); + end record test_vector; + + type test_vector_array is array (natural range <>) of test_vector; + + constant char_offset : integer := 2; + constant char_prepend : std_logic_vector(char_offset-1 downto 0) := "00"; + constant test_vectors : test_vector_array := + ( + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("10111100", '1'), ("10111100", '1'))), + (data => (("10111100", '1'), ("10111100", '1'))), + (data => (("10111100", '1'), ("10111100", '1'))), + (data => (("10111100", '1'), ("10111100", '1'))), + (data => (("10111100", '1'), ("10111100", '1'))), + (data => (("10111100", '1'), ("10111100", '1'))), + (data => (("10111100", '1'), ("10111100", '1'))), + (data => (("10111100", '1'), ("10111100", '1'))), + (data => (("10111100", '1'), ("10111100", '1'))), + (data => (("00011100", '1'), ("00011100", '1'))), -- 1st ILAS multiframe start + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("01111100", '1'), ("01111100", '1'))), -- 1st ILAS multiframe end + (data => (("00011100", '1'), ("00011100", '1'))), -- 2nd ILAS multiframe start + (data => (("10011100", '1'), ("10011100", '1'))), -- configuration start delimiter + (data => (("10101010", '0'), ("10101010", '0'))), -- DID + (data => (("01111110", '0'), ("01111110", '0'))), -- ADJCNT,BID + (data => (("01101010", '0'), ("01101010", '0'))), -- X,ADJDIR,PHADJ,LID + (data => (("11011110", '0'), ("11011110", '0'))), -- SCR,X,L + (data => (("11001100", '0'), ("11001100", '0'))), -- F + (data => (("01011111", '0'), ("01011111", '0'))), -- X, K + (data => (("00110011", '0'), ("00110011", '0'))), -- M + (data => (("10000011", '0'), ("10000011", '0'))), -- CS,X,N + (data => (("00111101", '0'), ("00111101", '0'))), -- SUBCLASSV,Nn + (data => (("00000000", '0'), ("00000000", '0'))), -- JESDV,S + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("01111100", '1'), ("01111100", '1'))), -- 2nd ILAS multiframe end + (data => (("00011100", '1'), ("00011100", '1'))), -- 3rd ILAS multiframe start + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("01111100", '1'), ("01111100", '1'))), -- 3rd ILAS multiframe end + (data => (("00011100", '1'), ("00011100", '1'))), -- 4th ILAS multiframe start + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("01111100", '1'), ("01111100", '1'))), -- 4th ILAS multiframe end + (data => (("10101010", '0'), ("01010101", '0'))), -- data + (data => (("10101001", '0'), ("01010110", '0'))), + (data => (("11111111", '0'), ("00000000", '0'))), -- data + (data => (("11111110", '0'), ("00000001", '0'))), + (data => (("00000001", '0'), ("11111110", '0'))), -- data + (data => (("11111111", '0'), ("00000000", '0'))) + ); + + constant char_clk_period : time := 1 ns; -- The clock period + constant frame_clk_period : time := 1 ns * F; -- The clock period + + signal di_transceiver_data : lane_input_array(0 to L-1); + signal di_lane_data : lane_data_array(0 to L-1); + + signal char_clk : std_logic := '0'; -- The clock + signal frame_clk : std_logic := '0'; -- The clock + signal reset : std_logic := '0'; -- The reset + + signal test_vec_index : integer := 0; + + signal co_lane_config : link_config; + signal co_nsynced : std_logic; + signal co_error : std_logic; + signal do_samples : samples_array (M-1 downto 0, S-1 downto 0) + (data(N - 1 downto 0), ctrl_bits(CS - 1 downto 0)); + signal co_correct_data : std_logic; + +begin -- architecture a1 + uut : entity work.jesd204b_rx + generic map ( + K => K, + CS => CS, + M => M, + S => S, + L => L, + F => F, + CF => CF, + N => N, + Nn => Nn) + port map ( + ci_char_clk => char_clk, + ci_frame_clk => frame_clk, + ci_reset => reset, + di_transceiver_data => di_transceiver_data, + co_lane_config => co_lane_config, + co_nsynced => co_nsynced, + co_error => co_error, + do_samples => do_samples, + co_correct_data => co_correct_data); + + encoders: for i in 0 to L-1 generate + encoder: entity work.an8b10b_encoder + port map ( + reset => reset, + clk => char_clk, + ena => '1', + KI => di_lane_data(i).k, + datain => di_lane_data(i).data, + dataout => di_transceiver_data(i)); + end generate encoders; + + char_clk <= not char_clk after char_clk_period/2; + frame_clk <= not frame_clk after frame_clk_period/2; + reset <= '1' after char_clk_period*2; + + test: process is + begin -- process test + wait for char_clk_period*2; + + for i in test_vectors'range loop + test_vec_index <= i; + di_lane_data <= test_vectors(i).data; + wait for char_clk_period; + end loop; -- i + + wait for 1000 ms; + end process test; +end architecture a1; diff --git a/testbench/jesd204b_rx_ils_tb.vhd b/testbench/jesd204b_rx_ils_tb.vhd new file mode 100644 index 0000000..f573a02 --- /dev/null +++ b/testbench/jesd204b_rx_ils_tb.vhd @@ -0,0 +1,195 @@ +library ieee; +use ieee.std_logic_1164.all; +use work.testing_functions.all; +use work.jesd204b_pkg.all; +use work.data_link_pkg.all; +use work.transport_pkg.all; + +entity jesd204b_rx_ils_tb is +end entity jesd204b_rx_ils_tb; + +architecture a1 of jesd204b_rx_ils_tb is + constant K : integer := 3; + constant CS : integer := 0; + constant M : integer := 2; -- Count of converters + constant S : integer := 1; -- Count of samples + constant L : integer := 2; -- Count of lanes + constant F : integer := 6; -- Count of octets in a frame per lane + constant CF : integer := 1; -- Count of control word bits + constant N : integer := 4; -- Sample size + constant Nn : integer := 4; + + type octet_data is record + data : std_logic_vector(7 downto 0); + k : std_logic; + end record octet_data; + + type lane_data_array is array (natural range <>) of octet_data; + type test_vector is record + data : lane_data_array(0 to L-1); + end record test_vector; + + type test_vector_array is array (natural range <>) of test_vector; + + constant char_offset : integer := 2; + constant char_prepend : std_logic_vector(char_offset-1 downto 0) := "00"; + constant test_vectors : test_vector_array := + ( + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("10111100", '1'), ("10111100", '1'))), + (data => (("10111100", '1'), ("10111100", '1'))), + (data => (("10111100", '1'), ("10111100", '1'))), + (data => (("10111100", '1'), ("10111100", '1'))), + (data => (("10111100", '1'), ("10111100", '1'))), + (data => (("10111100", '1'), ("10111100", '1'))), + (data => (("10111100", '1'), ("10111100", '1'))), + (data => (("10111100", '1'), ("10111100", '1'))), + (data => (("10111100", '1'), ("10111100", '1'))), + (data => (("00011100", '1'), ("00011100", '1'))), -- 1st ILAS multiframe start + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("01111100", '1'), ("01111100", '1'))), -- 1st ILAS multiframe end + (data => (("00011100", '1'), ("00011100", '1'))), -- 2nd ILAS multiframe start + (data => (("10011100", '1'), ("10011100", '1'))), -- configuration start delimiter + (data => (("10101010", '0'), ("10101010", '0'))), -- DID + (data => (("01111110", '0'), ("01111110", '0'))), -- ADJCNT,BID + (data => (("01101010", '0'), ("01101010", '0'))), -- X,ADJDIR,PHADJ,LID + (data => (("11011110", '0'), ("11011110", '0'))), -- SCR,X,L + (data => (("11001100", '0'), ("11001100", '0'))), -- F + (data => (("01011111", '0'), ("01011111", '0'))), -- X, K + (data => (("00110011", '0'), ("00110011", '0'))), -- M + (data => (("10000011", '0'), ("10000011", '0'))), -- CS,X,N + (data => (("00111101", '0'), ("00111101", '0'))), -- SUBCLASSV,Nn + (data => (("00000000", '0'), ("00000000", '0'))), -- JESDV,S + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("01111100", '1'), ("01111100", '1'))), -- 2nd ILAS multiframe end + (data => (("00011100", '1'), ("00011100", '1'))), -- 3rd ILAS multiframe start + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("01111100", '1'), ("01111100", '1'))), -- 3rd ILAS multiframe end + (data => (("00011100", '1'), ("00011100", '1'))), -- 4th ILAS multiframe start + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("00000000", '0'), ("00000000", '0'))), + (data => (("01111100", '1'), ("01111100", '1'))), -- 4th ILAS multiframe end + (data => (("00000000", '0'), ("00000000", '0'))), -- data + (data => (("11111111", '0'), ("11111111", '0'))) + ); + + constant char_clk_period : time := 1 ns; -- The clock period + constant frame_clk_period : time := 1 ns * F; -- The clock period + + signal di_transceiver_data : lane_input_array(L-1 downto 0); + signal di_lane_data : lane_data_array(L-1 downto 0); + + signal char_clk : std_logic := '0'; -- The clock + signal frame_clk : std_logic := '0'; -- The clock + signal reset : std_logic := '0'; -- The reset + + signal test_vec_index : integer := 0; + + signal co_lane_config : link_config; + signal co_nsynced : std_logic; + signal co_error : std_logic; + signal do_samples : samples_array (M-1 downto 0, S-1 downto 0) + (data(N - 1 downto 0), ctrl_bits(CS - 1 downto 0)); + signal co_correct_data : std_logic; + +begin -- architecture a1 + uut : entity work.jesd204b_rx + generic map ( + K => K, + CS => CS, + M => M, + S => S, + L => L, + F => F, + CF => CF, + N => N, + Nn => Nn) + port map ( + ci_char_clk => char_clk, + ci_frame_clk => frame_clk, + ci_reset => reset, + di_transceiver_data => di_transceiver_data, + co_lane_config => co_lane_config, + co_nsynced => co_nsynced, + co_error => co_error, + do_samples => do_samples, + co_correct_data => co_correct_data); + + encoders: for i in 0 to L-1 generate + encoder: entity work.an8b10b_encoder + port map ( + reset => reset, + clk => char_clk, + ena => '1', + KI => di_lane_data(i).k, + datain => di_lane_data(i).data, + dataout => di_transceiver_data(i)); + end generate encoders; + + char_clk <= not char_clk after char_clk_period/2; + frame_clk <= not frame_clk after frame_clk_period/2; + reset <= '1' after char_clk_period*2; + + test: process is + begin -- process test + wait for char_clk_period*2; + + for i in test_vectors'range loop + test_vec_index <= i; + di_lane_data <= test_vectors(i).data; + wait for char_clk_period; + end loop; -- i + + wait for 1000 ms; + end process test; +end architecture a1; diff --git a/testbench/jesd204b_rx_kchars_tb.vhd b/testbench/jesd204b_rx_kchars_tb.vhd new file mode 100644 index 0000000..cc7e842 --- /dev/null +++ b/testbench/jesd204b_rx_kchars_tb.vhd @@ -0,0 +1,132 @@ +library ieee; +use ieee.std_logic_1164.all; +use work.testing_functions.all; +use work.jesd204b_pkg.all; +use work.data_link_pkg.all; +use work.transport_pkg.all; + +entity jesd204b_rx_kchars_tb is +end entity jesd204b_rx_kchars_tb; + +-- first send some zeros +-- then just send k28.3 indefinitely + +architecture a1 of jesd204b_rx_kchars_tb is + constant K : integer := 5; + constant CS : integer := 0; + constant M : integer := 2; -- Count of converters + constant S : integer := 1; -- Count of samples + constant L : integer := 2; -- Count of lanes + constant F : integer := 5; -- Count of octets in a frame per lane + constant CF : integer := 1; -- Count of control word bits + constant N : integer := 4; -- Sample size + constant Nn : integer := 4; + + type test_vector is record + data : lane_input_array(0 to L-1); + end record test_vector; + + type test_vector_array is array (natural range <>) of test_vector; + + constant char_offset : integer := 2; + constant char_prepend : std_logic_vector(char_offset-1 downto 0) := "00"; + constant test_vectors : test_vector_array := + ( + (data => ("0000000000", "0000000000")), + (data => ("0000000000", "0000000000")), + (data => ("0000000000", "0000000000")), + (data => ("0000000000", "0000000000")), + (data => ("0011111010", "0011111010")), + (data => ("1100000101", "1100000101")), + (data => ("0011111010", "0011111010")), + (data => ("1100000101", "1100000101")), + (data => ("0011111010", "0011111010")), + (data => ("1100000101", "1100000101")), + (data => ("0011111010", "0011111010")), + (data => ("1100000101", "1100000101")), + (data => ("0011111010", "0011111010")), + (data => ("1100000101", "1100000101")), + (data => ("0011111010", "0011111010")), + (data => ("1100000101", "1100000101")), + (data => ("0011111010", "0011111010")), + (data => ("1100000101", "1100000101")), + (data => ("0011111010", "0011111010")), + (data => ("1100000101", "1100000101")), + (data => ("0011111010", "0011111010")), + (data => ("1100000101", "1100000101")), + (data => ("0011111010", "0011111010")), + (data => ("1100000101", "1100000101")), + (data => ("0011111010", "0011111010")), + (data => ("1100000101", "1100000101")), + (data => ("0011111010", "0011111010")), + (data => ("1100000101", "1100000101")), + (data => ("0011111010", "0011111010")), + (data => ("1100000101", "1100000101")) + ); + + constant char_clk_period : time := 1 ns; -- The clock period + constant frame_clk_period : time := 1 ns * F; -- The clock period + + signal di_transceiver_data : lane_input_array(L-1 downto 0); + + signal char_clk : std_logic := '0'; -- The clock + signal frame_clk : std_logic := '0'; -- The clock + signal reset : std_logic := '0'; -- The reset + + signal test_vec_index : integer := 0; + + signal co_lane_config : link_config; + signal co_nsynced : std_logic; + signal co_error : std_logic; + signal do_samples : samples_array (M-1 downto 0, S-1 downto 0) + (data(N - 1 downto 0), ctrl_bits(CS - 1 downto 0)); + signal co_correct_data : std_logic; + +begin -- architecture a1 + uut : entity work.jesd204b_rx + generic map ( + K => K, + CS => CS, + M => M, + S => S, + L => L, + F => F, + CF => CF, + N => N, + Nn => Nn) + port map ( + ci_char_clk => char_clk, + ci_frame_clk => frame_clk, + ci_reset => reset, + di_transceiver_data => di_transceiver_data, + co_lane_config => co_lane_config, + co_nsynced => co_nsynced, + co_error => co_error, + do_samples => do_samples, + co_correct_data => co_correct_data); + + char_clk <= not char_clk after char_clk_period/2; + frame_clk <= not frame_clk after frame_clk_period/2; + reset <= '1' after char_clk_period*2; + + test: process is + begin -- process test + wait for char_clk_period*2; + + for i in test_vectors'range loop + test_vec_index <= i; + if i = 0 then + for c in 0 to L-1 loop + di_transceiver_data(c) <= char_prepend & test_vectors(0).data(c)(9 downto char_offset); + end loop; -- l + else + for c in 0 to L-1 loop + di_transceiver_data(c) <= test_vectors(i-1).data(c)(char_offset - 1 downto 0) & test_vectors(i).data(c)(9 downto char_offset); + end loop; -- l + end if; + wait for char_clk_period; + end loop; -- i + + wait for 1000 ms; + end process test; +end architecture a1; -- 2.48.1