From fd6c573c72a600ed4f378e7ec46503b2b6fedf10 Mon Sep 17 00:00:00 2001 From: Pepping <pepping> Date: Thu, 10 Dec 2015 13:08:49 +0000 Subject: [PATCH] svn copy --- libraries/io/aduh/tb/vhdl/adc08d1020.vhd | 137 ++++++ libraries/io/aduh/tb/vhdl/adu_half.vhd | 179 ++++++++ libraries/io/aduh/tb/vhdl/tb_aduh_dd.vhd | 313 ++++++++++++++ .../io/aduh/tb/vhdl/tb_aduh_mean_sum.vhd | 152 +++++++ libraries/io/aduh/tb/vhdl/tb_aduh_pll.vhd | 409 ++++++++++++++++++ .../io/aduh/tb/vhdl/tb_aduh_power_sum.vhd | 151 +++++++ libraries/io/aduh/tb/vhdl/tb_aduh_verify.vhd | 260 +++++++++++ libraries/io/aduh/tb/vhdl/tb_lvdsh_dd.vhd | 142 ++++++ .../io/aduh/tb/vhdl/tb_lvdsh_dd_phs4.vhd | 301 +++++++++++++ libraries/io/aduh/tb/vhdl/tb_lvdsh_dd_wb4.vhd | 230 ++++++++++ .../io/aduh/tb/vhdl/tb_mms_aduh_quad.vhd | 338 +++++++++++++++ .../io/aduh/tb/vhdl/tb_tb_lvdsh_dd_phs4.vhd | 53 +++ .../io/aduh/tb/vhdl/tb_tb_lvdsh_dd_wb4.vhd | 46 ++ 13 files changed, 2711 insertions(+) create mode 100644 libraries/io/aduh/tb/vhdl/adc08d1020.vhd create mode 100644 libraries/io/aduh/tb/vhdl/adu_half.vhd create mode 100644 libraries/io/aduh/tb/vhdl/tb_aduh_dd.vhd create mode 100644 libraries/io/aduh/tb/vhdl/tb_aduh_mean_sum.vhd create mode 100644 libraries/io/aduh/tb/vhdl/tb_aduh_pll.vhd create mode 100644 libraries/io/aduh/tb/vhdl/tb_aduh_power_sum.vhd create mode 100644 libraries/io/aduh/tb/vhdl/tb_aduh_verify.vhd create mode 100644 libraries/io/aduh/tb/vhdl/tb_lvdsh_dd.vhd create mode 100644 libraries/io/aduh/tb/vhdl/tb_lvdsh_dd_phs4.vhd create mode 100644 libraries/io/aduh/tb/vhdl/tb_lvdsh_dd_wb4.vhd create mode 100644 libraries/io/aduh/tb/vhdl/tb_mms_aduh_quad.vhd create mode 100644 libraries/io/aduh/tb/vhdl/tb_tb_lvdsh_dd_phs4.vhd create mode 100644 libraries/io/aduh/tb/vhdl/tb_tb_lvdsh_dd_wb4.vhd diff --git a/libraries/io/aduh/tb/vhdl/adc08d1020.vhd b/libraries/io/aduh/tb/vhdl/adc08d1020.vhd new file mode 100644 index 0000000000..7f5d96d057 --- /dev/null +++ b/libraries/io/aduh/tb/vhdl/adc08d1020.vhd @@ -0,0 +1,137 @@ +------------------------------------------------------------------------------- +-- +-- Copyright (C) 2010 +-- 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; + +-- Purpose: Behavioral model of the National adc08d1020 ADC on the ADU +-- Description: +-- The adc08d1020 model features: +-- . the sampling analogue input data via AI, AQ and overflow via AOVR +-- . offset binary ADC data format +-- . the internal ADC test pattern generation when test_pattern_en is '1' +-- . allows dynamic setting of skew for each LVDS line + +ENTITY adc08d1020 IS + GENERIC ( + g_clk_period : TIME := 1250 ps; -- Sample clock period of CLK + g_dclk_init_phase : NATURAL := 0 -- When 0 then use default phase for DCLK, else use the other DDR phase + ); + PORT ( + AI : IN INTEGER := 0; + AQ : IN INTEGER := 0; + AOVR : IN STD_LOGIC := '0'; + CLK : IN STD_LOGIC := '0'; + DCLK : OUT STD_LOGIC; + DCLK_RST : IN STD_LOGIC := '0'; + DI : OUT STD_LOGIC_VECTOR(7 DOWNTO 0); + DQ : OUT STD_LOGIC_VECTOR(7 DOWNTO 0); + OVR : OUT STD_LOGIC; + + test_pattern_en : IN STD_LOGIC := '0'; + lvds_skew_di : IN t_natural_arr(7 DOWNTO 0) := (OTHERS=>0); -- ps unit + lvds_skew_dq : IN t_natural_arr(7 DOWNTO 0) := (OTHERS=>0); -- ps unit + lvds_skew_ovr : IN NATURAL := 0; -- ps unit + lvds_skew_dclk : IN NATURAL := 0 -- ps unit + ); +END adc08d1020; + + +ARCHITECTURE beh OF adc08d1020 IS + + CONSTANT c_nof_adc : NATURAL := 2; -- for AI and AQ + + TYPE t_adc_dat_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(7 DOWNTO 0); + + SIGNAL adc_dat : t_adc_dat_arr(0 TO c_nof_adc-1); -- [0] = AI, [1] = AQ + SIGNAL adc_ovr : STD_LOGIC; + + SIGNAL tp_cnt : NATURAL := 0; -- test pattern sequence index counter + + SIGNAL dclk_dis : STD_LOGIC := '0'; + SIGNAL ddr_clk : STD_LOGIC := sel_a_b(g_dclk_init_phase, '1', '0'); + +BEGIN + + -- Sample the analogue I and Q input using the falling edge of the sample clock CLK + p_sample : PROCESS(CLK) + BEGIN + IF falling_edge(CLK) THEN + IF test_pattern_en='0' THEN + adc_dat(0) <= offset_binary(TO_SVEC(AI, 8)); + adc_dat(1) <= offset_binary(TO_SVEC(AQ, 8)); + adc_ovr <= AOVR; + ELSE + -- TP_I TP_Q TP_OV + -- T0 02h 01h 0 + -- T1 FDh FEh 1 + -- T2 02h 01h 0 + -- T3 02h 01h 0 + -- T4 FDh FEh 1 + -- T5 FDh FEh 1 + -- T6 02h 01h 0 + -- T7 02h 01h 0 + -- T8 FDh FEh 1 + -- T9 02h 01h 0 + CASE tp_cnt IS + WHEN 0 | 2 | 3 | 6 | 7 | 9 => adc_dat(0) <= TO_UVEC(16#02#, 8); adc_dat(1) <= TO_UVEC(16#01#, 8); adc_ovr <= '0'; + WHEN OTHERS => adc_dat(0) <= TO_UVEC(16#FD#, 8); adc_dat(1) <= TO_UVEC(16#FE#, 8); adc_ovr <= '1'; + END CASE; + tp_cnt <= tp_cnt + 1; + IF tp_cnt = 9 THEN + tp_cnt <= 0; + END IF; + END IF; + END IF; + END PROCESS; + + -- Disable the DDR clock during the DCLK_RST and delay the DDR clock after release of DCLK_RST + p_dclk_dis : PROCESS(DCLK_RST, CLK) + VARIABLE v_cnt : NATURAL; + BEGIN + IF DCLK_RST='1' THEN + dclk_dis <= '1'; + v_cnt := 0; + ELSIF rising_edge(CLK) THEN + dclk_dis <= '0'; + IF v_cnt<8 THEN -- latency 3 or 4 CLK cycles and 4 ns propagation delay, so in total about 8 CLK cycles + dclk_dis <= '1'; + v_cnt := v_cnt+1; + END IF; + END IF; + END PROCESS; + + -- Create the DDR clock that is half the rate of the sample clock CLK + ddr_clk <= '0' WHEN dclk_dis='1' ELSE NOT ddr_clk WHEN falling_edge(CLK); + + -- Apply the skew to each LVDS trace + gen_skew : FOR S IN 7 DOWNTO 0 GENERATE + DI(S) <= TRANSPORT adc_dat(0)(S) AFTER lvds_skew_di(S)* 1 ps; + DQ(S) <= TRANSPORT adc_dat(1)(S) AFTER lvds_skew_dq(S)* 1 ps; + END GENERATE; + + OVR <= TRANSPORT adc_ovr AFTER lvds_skew_ovr * 1 ps; + DCLK <= TRANSPORT ddr_clk AFTER lvds_skew_dclk * 1 ps; + +END beh; diff --git a/libraries/io/aduh/tb/vhdl/adu_half.vhd b/libraries/io/aduh/tb/vhdl/adu_half.vhd new file mode 100644 index 0000000000..d377d573f6 --- /dev/null +++ b/libraries/io/aduh/tb/vhdl/adu_half.vhd @@ -0,0 +1,179 @@ +------------------------------------------------------------------------------- +-- +-- Copyright (C) 2010 +-- 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, i2c_lib; +USE IEEE.STD_LOGIC_1164.ALL; +USE IEEE.NUMERIC_STD.ALL; +USE common_lib.common_pkg.ALL; +USE i2c_lib.i2c_dev_adu_pkg.ALL; + +-- Purpose: Behavioral model of the half ADU including the rewiring on the +-- backplane (AUB) +-- Description: +-- . The half ADU consists of one adc08d1020 which has two ADCs that output +-- via DI[7:0] and DQ[7:0]. The DI port is wired default, but the DQ port +-- is cross-wired on the ADU-UniBoard backplane PCB to ease layout. +-- . Models the I2C peripherals on ADU + +ENTITY adu_half IS + GENERIC ( + g_dclk_init_phase : NATURAL := 0 -- When 0 then use default phase for DCLK, else use the other DDR phase + ); + PORT ( + AI : IN INTEGER := 0; + AQ : IN INTEGER := 0; + AOVR : IN STD_LOGIC := '0'; + CLK : IN STD_LOGIC := '0'; + DCLK : OUT STD_LOGIC; + DCLK_RST : IN STD_LOGIC := '1'; -- inverted + DI : OUT STD_LOGIC_VECTOR(7 DOWNTO 0); + DQ : OUT STD_LOGIC_VECTOR(7 DOWNTO 0); + OVR : OUT STD_LOGIC; + SCL : INOUT STD_LOGIC; + SDA : INOUT STD_LOGIC; + + test_pattern_en : IN STD_LOGIC := '0'; + lvds_skew_di : IN t_natural_arr(7 DOWNTO 0) := (OTHERS=>0); -- ps unit + lvds_skew_dq : IN t_natural_arr(7 DOWNTO 0) := (OTHERS=>0); -- ps unit + lvds_skew_ovr : IN NATURAL := 0; -- ps unit + lvds_skew_dclk : IN NATURAL := 0 -- ps unit + ); +END adu_half; + + +ARCHITECTURE beh OF adu_half IS + + CONSTANT c_dclk_rst_invert : BOOLEAN := FALSE; -- Default FALSE because DCLK_RST on ADC is active high, use TRUE to model for a P/N cross + + -- Model I2C slaves on the bus + CONSTANT c_max1618_address : STD_LOGIC_VECTOR := TO_UVEC(I2C_ADU_MAX1617_ADR, 7); -- MAX1618 address MID MID + CONSTANT c_max1618_temp : INTEGER := 60; + CONSTANT c_io_expander_address : STD_LOGIC_VECTOR := TO_UVEC(I2C_ADU_PCA9555_ADR, 7); -- ADR_PCA9555 address + + SIGNAL DI_rewire : STD_LOGIC_VECTOR(7 DOWNTO 0); + SIGNAL DQ_rewire : STD_LOGIC_VECTOR(7 DOWNTO 0); + + SIGNAL DCLK_RST_rewire : STD_LOGIC; + + -- IO expander + SIGNAL iobank0 : STD_LOGIC_VECTOR(7 DOWNTO 0); + SIGNAL iobank1 : STD_LOGIC_VECTOR(7 DOWNTO 0); + + -- IO expander ADU + SIGNAL adu_sclk : STD_LOGIC; + SIGNAL adu_sdata : STD_LOGIC; + SIGNAL adu_led_scs_n : STD_LOGIC; + SIGNAL adu_cal_adc : STD_LOGIC; + SIGNAL adu_pwr_ctrl : STD_LOGIC_VECTOR(1 DOWNTO 0); + SIGNAL adu_pwr_ctrl_1_dig : STD_LOGIC; + SIGNAL adu_pwr_ctrl_0_ana : STD_LOGIC; + SIGNAL adu_ctrl : STD_LOGIC_VECTOR(3 DOWNTO 0); + SIGNAL adu_ctrl_0_atten_le : STD_LOGIC; + SIGNAL adu_ctrl_1_modem_on : STD_LOGIC; + SIGNAL adu_ctrl_2_atten_le : STD_LOGIC; + SIGNAL adu_ctrl_3_modem_on : STD_LOGIC; + + SIGNAL adu_atten_ctrl : STD_LOGIC_VECTOR(5 DOWNTO 0); + +BEGIN + + -- I port A and C wire default + DI <= DI_rewire; + + -- Q port B and D are rewired on AUB and on the single BN-ADU connector board: + DQ(0) <= DQ_rewire(6); + DQ(1) <= DQ_rewire(7); + DQ(2) <= DQ_rewire(4); + DQ(3) <= DQ_rewire(5); + DQ(4) <= DQ_rewire(2); + DQ(5) <= DQ_rewire(3); + DQ(6) <= DQ_rewire(0); + DQ(7) <= DQ_rewire(1); + + -- Model swapped P/N pins at the UniBoard back node by a NOT, see also in BACK_NODE_adc_pins.tcl and aduh_dd.vhd + DCLK_RST_rewire <= DCLK_RST WHEN c_dclk_rst_invert=FALSE ELSE NOT DCLK_RST; + + u_adc : ENTITY work.adc08d1020 + GENERIC MAP ( + g_dclk_init_phase => g_dclk_init_phase + ) + PORT MAP ( + AI => AI, + AQ => AQ, + AOVR => AOVR, + CLK => CLK, + DCLK => DCLK, + DCLK_RST => DCLK_RST_rewire, + DI => DI_rewire, + DQ => DQ_rewire, + OVR => OVR, + + test_pattern_en => test_pattern_en, + lvds_skew_di => lvds_skew_di, + lvds_skew_dq => lvds_skew_dq, + lvds_skew_ovr => lvds_skew_ovr, + lvds_skew_dclk => lvds_skew_dclk + ); + + -- I2C bus + SCL <= 'H'; -- model I2C pull up + SDA <= 'H'; -- model I2C pull up + + u_sens_temp : ENTITY i2c_lib.dev_max1618 + GENERIC MAP ( + g_address => c_max1618_address + ) + PORT MAP ( + scl => SCL, + sda => SDA, + temp => c_max1618_temp + ); + + u_io_expander : ENTITY i2c_lib.dev_pca9555 + GENERIC MAP ( + g_address => c_io_expander_address + ) + PORT MAP ( + scl => SCL, + sda => SDA, + iobank0 => iobank0, + iobank1 => iobank1 + ); + + -- ADU interpretation of the IO expander outputs + adu_sclk <= iobank0(4); + adu_sdata <= iobank0(5); + adu_led_scs_n <= iobank0(7); + adu_cal_adc <= iobank1(7); + adu_pwr_ctrl <= iobank0(6) & iobank1(6); + adu_pwr_ctrl_1_dig <= adu_pwr_ctrl(1); + adu_pwr_ctrl_0_ana <= adu_pwr_ctrl(0); + + adu_ctrl <= iobank0(3 DOWNTO 0); + adu_ctrl_0_atten_le <= adu_ctrl(0); + adu_ctrl_1_modem_on <= adu_ctrl(1); + adu_ctrl_2_atten_le <= adu_ctrl(2); + adu_ctrl_3_modem_on <= adu_ctrl(3); + + adu_atten_ctrl <= iobank1(5 DOWNTO 0); + +END beh; diff --git a/libraries/io/aduh/tb/vhdl/tb_aduh_dd.vhd b/libraries/io/aduh/tb/vhdl/tb_aduh_dd.vhd new file mode 100644 index 0000000000..cb164a40b8 --- /dev/null +++ b/libraries/io/aduh/tb/vhdl/tb_aduh_dd.vhd @@ -0,0 +1,313 @@ +------------------------------------------------------------------------------- +-- +-- Copyright (C) 2011 +-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.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/>. +-- +------------------------------------------------------------------------------- + +-- Usage: +-- > as 10 +-- > run -all +-- > observe verify_data as hexadecimal in Wave window, shows the incrementing ADC data when lvds_skew_di = c_lvds_skew_zero and lvds_skew_dq = c_lvds_skew_zero + +LIBRARY IEEE, common_lib, dp_lib; +USE IEEE.STD_LOGIC_1164.ALL; +USE IEEE.NUMERIC_STD.ALL; +USE common_lib.common_pkg.ALL; +USE dp_lib.dp_stream_pkg.ALL; +USE dp_lib.tb_dp_pkg.ALL; +USE work.aduh_dd_pkg.ALL; + +ENTITY tb_aduh_dd IS +END tb_aduh_dd; + +ARCHITECTURE tb OF tb_aduh_dd IS + + -- ADU board + CONSTANT c_adc_w : NATURAL := 8; + CONSTANT c_ana_diff : NATURAL := 16; -- analogue offset value between the port A, B, C, D + + CONSTANT c_lvds_skew_zero : t_natural_arr(c_adc_w-1 DOWNTO 0) := (OTHERS=>0); -- ps unit + CONSTANT c_lvds_skew_init : t_natural_arr(c_adc_w-1 DOWNTO 0) := (350, 300, 250, 200, 150, 100, 50, 0); -- ps unit + CONSTANT c_lvds_skew_clk : NATURAL := 35; -- ps unit + + CONSTANT c_dclk_init_phase_a : NATURAL := 0; + CONSTANT c_dclk_init_phase_b : NATURAL := 0; + + -- ADU handler + + --TYPE t_c_aduh_dd_ai IS RECORD + -- nof_sp : NATURAL; -- = 4 + -- nof_adu : NATURAL; -- = 2 + -- nof_ports : NATURAL; -- = 2 + -- port_w : NATURAL; -- = 8 + -- dd_factor : NATURAL; -- = 2 + -- rx_factor : NATURAL; -- = 2 + -- deskew : t_c_aduh_delays; -- = (0, 0, (OTHERS=>0), (OTHERS=>0), (OTHERS=>0), (OTHERS=>0)) -- clock: a, b, data: a, b, c, d + --END RECORD; + --CONSTANT c_ai : t_c_aduh_dd_ai := c_aduh_dd_ai; -- use defaults + CONSTANT c_ai : t_c_aduh_dd_ai := (4, 2, 2, c_adc_w, 2, 2, TRUE, FALSE, (7, 7, (0, 1, 2, 3, 4, 5, 6, 7), + (0, 1, 2, 3, 4, 5, 6, 7), + (0, 1, 2, 3, 4, 5, 6, 7), + (0, 1, 2, 3, 4, 5, 6, 7))); -- use defaults, compensate for c_lvds_skew_init + + CONSTANT c_dp_factor : NATURAL := c_ai.rx_factor * c_ai.dd_factor; -- = 4 = 2 * 2 + + CONSTANT c_sample_period : TIME := 1250 ps; -- 800 MTps + CONSTANT c_dp_clk_period : TIME := c_sample_period*c_dp_factor; -- 200 MHz + + CONSTANT c_dp_clk_skew : NATURAL := 235; -- ps unit, model skew between dp_clk and SCLK, both are in lock with the same reference + + CONSTANT c_dp_phs_clk_step : TIME := c_dp_clk_period/32; -- the PLL can output clocks with phase shifts of 360/32 = 11.25 degrees + CONSTANT c_dp_phs_clk_period : NATURAL := 32; -- number of dp_clk periods per dp_phs_clk period + CONSTANT c_nof_dp_phs_clk : NATURAL := 1; + + CONSTANT c_dp_dat_w : NATURAL := c_dp_factor * c_adc_w; -- 32 bit + + CONSTANT c_rl : NATURAL := 1; + CONSTANT c_verify_delay : NATURAL := 10; + CONSTANT c_verify_period : TIME := 3 us; + + TYPE t_dp_data_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(c_dp_dat_w-1 DOWNTO 0); + + -- Analogue + SIGNAL ANA_DAT : STD_LOGIC_VECTOR(c_ai.port_w-1 DOWNTO 0) := (OTHERS=>'0'); -- Common ADC reference data source + SIGNAL ANA_A : STD_LOGIC_VECTOR(c_ai.port_w-1 DOWNTO 0) := (OTHERS=>'0'); -- ADC port A + SIGNAL ANA_B : STD_LOGIC_VECTOR(c_ai.port_w-1 DOWNTO 0) := (OTHERS=>'0'); -- ADC port B + SIGNAL ANA_C : STD_LOGIC_VECTOR(c_ai.port_w-1 DOWNTO 0) := (OTHERS=>'0'); -- ADC port C + SIGNAL ANA_D : STD_LOGIC_VECTOR(c_ai.port_w-1 DOWNTO 0) := (OTHERS=>'0'); -- ADC port D + SIGNAL SCLK : STD_LOGIC := '1'; -- central sample clock = 800 MHz + SIGNAL DCLK_AB : STD_LOGIC; -- digital lvds clock = 400 MHz (DDR) + SIGNAL DCLK_CD : STD_LOGIC; -- digital lvds clock = 400 MHz (DDR) + SIGNAL DCLK_RST_AB : STD_LOGIC; -- synchronise digital lvds clock + SIGNAL DCLK_RST_CD : STD_LOGIC; -- synchronise digital lvds clock + SIGNAL DIG_A : STD_LOGIC_VECTOR(c_ai.port_w-1 DOWNTO 0); + SIGNAL DIG_B : STD_LOGIC_VECTOR(c_ai.port_w-1 DOWNTO 0); + SIGNAL DIG_C : STD_LOGIC_VECTOR(c_ai.port_w-1 DOWNTO 0); + SIGNAL DIG_D : STD_LOGIC_VECTOR(c_ai.port_w-1 DOWNTO 0); + + SIGNAL test_pattern_en : STD_LOGIC := '0'; + SIGNAL lvds_skew_di : t_natural_arr(c_ai.port_w-1 DOWNTO 0) := c_lvds_skew_zero; --c_lvds_skew_init; + SIGNAL lvds_skew_dq : t_natural_arr(c_ai.port_w-1 DOWNTO 0) := c_lvds_skew_zero; --c_lvds_skew_init; + SIGNAL lvds_skew_dclk : NATURAL := c_lvds_skew_clk; + + -- Digital streaming + SIGNAL tb_end : STD_LOGIC := '0'; + SIGNAL dp_clk_ref : STD_LOGIC := '1'; -- digital data path clock = 200 MHz (deser factor 4); + SIGNAL dp_clk : STD_LOGIC; + SIGNAL dp_rst : STD_LOGIC; + SIGNAL dp_phs_cnt : NATURAL := 0; + SIGNAL dp_phs_clk : STD_LOGIC := '1'; + SIGNAL dp_phs_clk_vec : STD_LOGIC_VECTOR(c_nof_dp_phs_clk-1 DOWNTO 0); + + SIGNAL dp_sosi_arr : t_dp_sosi_arr(0 TO c_ai.nof_sp-1); + + -- MM Interface + SIGNAL ab_locked : STD_LOGIC; + SIGNAL ab_stable : STD_LOGIC; + SIGNAL ab_stable_ack : STD_LOGIC := '0'; + + SIGNAL cd_locked : STD_LOGIC; + SIGNAL cd_stable : STD_LOGIC; + SIGNAL cd_stable_ack : STD_LOGIC := '0'; + + -- Verify + SIGNAL verify_en : STD_LOGIC_VECTOR(0 TO c_ai.nof_sp-1) := (OTHERS=>'0'); + SIGNAL verify_en_all : STD_LOGIC := '0'; + SIGNAL verify_valid : STD_LOGIC_VECTOR(0 TO c_ai.nof_sp-1) := (OTHERS=>'0'); + SIGNAL verify_done : STD_LOGIC_VECTOR(0 TO c_ai.nof_sp-1) := (OTHERS=>'0'); + SIGNAL verify_data : t_dp_data_arr( 0 TO c_ai.nof_sp-1); + SIGNAL prev_verify_data : t_dp_data_arr( 0 TO c_ai.nof_sp-1); + SIGNAL sl0 : STD_LOGIC := '0'; + SIGNAL sl1 : STD_LOGIC := '1'; + SIGNAL slv0 : STD_LOGIC_VECTOR(1 DOWNTO 0) := "00"; + +BEGIN + + tb_end <= '0', '1' AFTER 10 us; + + ----------------------------------------------------------------------------- + -- ADU0 and ADU1 for BN port A,B and C,D + ----------------------------------------------------------------------------- + + -- Same analogue reference signal for all ADC, use incrementing data to ease the verification + ANA_DAT <= INCR_UVEC(ANA_DAT, 1) WHEN rising_edge(SCLK); + ANA_A <= INCR_UVEC(ANA_DAT, 0*c_ana_diff); + ANA_B <= INCR_UVEC(ANA_DAT, 1*c_ana_diff); + ANA_C <= INCR_UVEC(ANA_DAT, 2*c_ana_diff); + ANA_D <= INCR_UVEC(ANA_DAT, 3*c_ana_diff); + + -- Same sample clock for all ADC + SCLK <= NOT SCLK OR tb_end AFTER c_sample_period/2; + + -- ADU model with National ADC and including backplane rewiring on AUB + u_adu_AB : ENTITY work.adu_half + GENERIC MAP ( + g_dclk_init_phase => c_dclk_init_phase_a + ) + PORT MAP ( + AI => TO_SINT(ANA_A), + AQ => TO_SINT(ANA_B), + CLK => SCLK, + DCLK => DCLK_AB, + DCLK_RST => DCLK_RST_AB, + DI => DIG_A, + DQ => DIG_B, + + test_pattern_en => test_pattern_en, + lvds_skew_di => lvds_skew_di, + lvds_skew_dq => lvds_skew_dq, + lvds_skew_dclk => lvds_skew_dclk + ); + + u_adu_CD : ENTITY work.adu_half + GENERIC MAP ( + g_dclk_init_phase => c_dclk_init_phase_b + ) + PORT MAP ( + AI => TO_SINT(ANA_C), + AQ => TO_SINT(ANA_D), + CLK => SCLK, + DCLK => DCLK_CD, + DCLK_RST => DCLK_RST_CD, + DI => DIG_C, + DQ => DIG_D, + + test_pattern_en => test_pattern_en, + lvds_skew_di => lvds_skew_di, + lvds_skew_dq => lvds_skew_dq, + lvds_skew_dclk => lvds_skew_dclk + ); + + ----------------------------------------------------------------------------- + -- Stimuli + ----------------------------------------------------------------------------- + + dp_rst <= '1', '0' AFTER c_dp_clk_period*7; + dp_clk_ref <= NOT dp_clk_ref OR tb_end AFTER c_dp_clk_period/2; + dp_clk <= TRANSPORT dp_clk_ref AFTER c_dp_clk_skew * 1 ps; + + -- Create DP phase reference clock + p_dp_phs_clk : PROCESS(dp_clk) + BEGIN + IF c_dp_phs_clk_period=1 THEN + dp_phs_clk <= dp_clk; + ELSIF rising_edge(dp_clk) THEN + IF dp_phs_cnt MOD (c_dp_phs_clk_period/2) = 0 THEN + dp_phs_clk <= NOT dp_phs_clk; + END IF; + IF dp_phs_cnt=c_dp_phs_clk_period-1 THEN + dp_phs_cnt<=0; + ELSE + dp_phs_cnt<=dp_phs_cnt+1; + END IF; + END IF; + END PROCESS; + + gen_dp_phs_clk_vec : FOR I IN c_nof_dp_phs_clk-1 DOWNTO 0 GENERATE + dp_phs_clk_vec(I) <= TRANSPORT dp_phs_clk AFTER I*c_dp_phs_clk_step; + END GENERATE; + + u_aduh_dd : ENTITY work.aduh_dd + GENERIC MAP ( + g_ai => c_ai + ) + PORT MAP ( + -- LVDS Interface + -- . g_ai.nof_sp = 4, fixed support 4 signal paths A,B,C,D + ADC_BI_A => DIG_A, + ADC_BI_B => DIG_B, + ADC_BI_C => DIG_C, + ADC_BI_D => DIG_D, + + ADC_BI_A_CLK => DCLK_AB, + ADC_BI_D_CLK => DCLK_CD, + + ADC_BI_A_CLK_RST => DCLK_RST_AB, + ADC_BI_D_CLK_RST => DCLK_RST_CD, + + -- MM Interface + ab_locked => ab_locked, + ab_stable => ab_stable, + ab_stable_ack => ab_stable_ack, + + cd_locked => cd_locked, + cd_stable => cd_stable, + cd_stable_ack => cd_stable_ack, + + -- DP Interface + dp_rst => dp_rst, + dp_clk => dp_clk, + dp_phs_clk_vec => dp_phs_clk_vec, + + -- . Streaming + src_out_arr => dp_sosi_arr + ); + + ----------------------------------------------------------------------------- + -- Verify dp_sosi_arr + -- . verify that that the test has run at all + -- . verify that the valid data per ADC port is incrementing + -- . verify that the valid data between the ADC ports has the correct diff (alignment) + ----------------------------------------------------------------------------- + + -- Verify that that the test has run at all + verify_en_all <= vector_and(verify_en); + + p_verify_run : PROCESS + BEGIN + -- Wait some time + WAIT FOR c_verify_period; + IF verify_en_all/='1' THEN + REPORT "ADUH using DD: No valid data, test may not be running." SEVERITY ERROR; + END IF; + WAIT; + END PROCESS; + + verify_valid(0) <= dp_sosi_arr(0).valid; + verify_valid(1) <= dp_sosi_arr(1).valid; + verify_valid(2) <= dp_sosi_arr(2).valid; + verify_valid(3) <= dp_sosi_arr(3).valid; + + gen_verify : FOR I IN 0 TO c_ai.nof_sp-1 GENERATE + + -- Enable verify after first valid data and keep it enabled + proc_dp_verify_en(c_verify_delay, dp_rst, dp_clk, verify_valid(I), verify_en(I)); + + -- Verify that the symbols in the data are incrementing per ADC (ready not used, empty not used) + verify_data(I) <= dp_sosi_arr(I).data(c_dp_dat_w-1 DOWNTO 0); + proc_dp_verify_symbols(c_rl, c_dp_dat_w, c_adc_w, dp_clk, verify_en(I), sl1, dp_sosi_arr(I).valid, sl0, verify_data(I), slv0, prev_verify_data(I)); + + -- Verify the data alignment between the ADCs by checking the expected c_ana_diff offset + p_alignment : PROCESS(dp_clk) + BEGIN + IF I > 0 THEN + IF rising_edge(dp_clk) THEN + IF verify_en_all='1' THEN + FOR J IN 0 TO c_dp_factor-1 LOOP + IF verify_data(I)((J+1)*c_adc_w-1 DOWNTO J*c_adc_w) /= INCR_UVEC(verify_data(I-1)((J+1)*c_adc_w-1 DOWNTO J*c_adc_w), c_ana_diff) THEN + REPORT "ADUH using DD: Wrong alignment between ADCs." SEVERITY ERROR; + END IF; + END LOOP; + END IF; + END IF; + END IF; + END PROCESS; + + END GENERATE; -- gen_verify + +END tb; diff --git a/libraries/io/aduh/tb/vhdl/tb_aduh_mean_sum.vhd b/libraries/io/aduh/tb/vhdl/tb_aduh_mean_sum.vhd new file mode 100644 index 0000000000..dc2610cccb --- /dev/null +++ b/libraries/io/aduh/tb/vhdl/tb_aduh_mean_sum.vhd @@ -0,0 +1,152 @@ +------------------------------------------------------------------------------- +-- +-- Copyright (C) 2010 +-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.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, 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 common_lib.tb_common_mem_pkg.ALL; +USE common_lib.common_lfsr_sequences_pkg.ALL; +USE dp_lib.dp_stream_pkg.ALL; +USE dp_lib.tb_dp_pkg.ALL; + + +-- Usage: +-- > as 10 +-- > run 1 us +-- observe in_sosi, sum and sum_sync in wave window +-- expected sum after sum_sync are: 0, 120, 376, ... + + +ENTITY tb_aduh_mean_sum IS + GENERIC ( + g_random_control : BOOLEAN := TRUE -- use TRUE for random stream flow control, use FALSE for initial debugging + ); +END tb_aduh_mean_sum; + + +ARCHITECTURE tb OF tb_aduh_mean_sum IS + + CONSTANT clk_period : TIME := 10 ns; + + CONSTANT c_rl : NATURAL := 1; + CONSTANT c_symbol_w : NATURAL := 8; + CONSTANT c_nof_symbols_per_data : NATURAL := 4; + CONSTANT c_nof_symbols_per_block : NATURAL := 8; -- nof symbols (= ADC samples) per block + + CONSTANT c_sum_truncate : BOOLEAN := TRUE; + CONSTANT c_sum_w : NATURAL := c_word_w; -- = 32 + + CONSTANT c_data_w : NATURAL := c_nof_symbols_per_data*c_symbol_w; + + CONSTANT c_nof_sync : NATURAL := 10; + CONSTANT c_nof_block_per_sync : NATURAL := 2; + CONSTANT c_nof_symbols_per_sync : NATURAL := c_nof_block_per_sync * c_nof_symbols_per_block; + + CONSTANT c_nof_accumulations : NATURAL := c_nof_symbols_per_sync; -- integration time in symbols + + SIGNAL rst : STD_LOGIC; + SIGNAL clk : STD_LOGIC := '1'; + + SIGNAL random_0 : STD_LOGIC_VECTOR(14 DOWNTO 0) := (OTHERS=>'0'); -- use different lengths to have different random sequences + + SIGNAL st_en : STD_LOGIC := '1'; + SIGNAL st_sosi : t_dp_sosi := c_dp_sosi_rst; + SIGNAL st_siso : t_dp_siso := c_dp_siso_rdy; + + SIGNAL bsn : NATURAL; + + SIGNAL in_sosi : t_dp_sosi := c_dp_sosi_rst; + + SIGNAL sum : STD_LOGIC_VECTOR(c_sum_w-1 DOWNTO 0); + SIGNAL sum_sync : STD_LOGIC; + SIGNAL sum_sop : STD_LOGIC; + +BEGIN + + clk <= NOT clk AFTER clk_period/2; + rst <= '1', '0' AFTER clk_period*5; + + -- ST domain + gen_random_control : IF g_random_control=TRUE GENERATE + random_0 <= func_common_random(random_0) WHEN rising_edge(clk); + --st_en <= NOT st_en WHEN rising_edge(clk); + --st_en <= random_0(random_0'HIGH); + END GENERATE; -- else the st_en line is always active + + p_st_stimuli : PROCESS + VARIABLE v_symbol : NATURAL := 0; + BEGIN + st_sosi <= c_dp_sosi_rst; + proc_common_wait_until_low(clk, rst); + proc_common_wait_some_cycles(clk, 5); + + -- Run some sync intervals with DSP counter data for the data field + st_sosi.sync <= '1'; -- first sync + WAIT UNTIL rising_edge(clk); + FOR I IN 0 TO c_nof_sync-1 LOOP + FOR J IN 0 TO c_nof_block_per_sync-2 LOOP -- provide sop and eop for block reference + proc_dp_gen_block_data(c_rl, TRUE, c_data_w, c_symbol_w, v_symbol, 0, 0, c_nof_symbols_per_block, 0, 0, '0', "0", clk, st_en, st_siso, st_sosi); -- no sync + v_symbol := v_symbol + c_nof_symbols_per_block; + END LOOP; + proc_dp_gen_block_data(c_rl, TRUE, c_data_w, c_symbol_w, v_symbol, 0, 0, c_nof_symbols_per_block, 0, 0, '1', "0", clk, st_en, st_siso, st_sosi); -- next sync + v_symbol := v_symbol + c_nof_symbols_per_block; + END LOOP; + + st_sosi <= c_dp_sosi_rst; + WAIT; + END PROCESS; + + -- Time stimuli + bsn <= bsn + 1 WHEN rising_edge(clk) AND st_sosi.sync='1'; + + -- Add BSN to the ST data + p_in_sosi : PROCESS(st_sosi, bsn) + BEGIN + in_sosi <= st_sosi; + in_sosi.bsn <= TO_DP_BSN(bsn); + END PROCESS; + + u_dut : ENTITY work.aduh_mean_sum + GENERIC MAP ( + g_symbol_w => c_symbol_w, + g_nof_symbols_per_data => c_nof_symbols_per_data, -- big endian in_data, t0 in MSSymbol, so [h:0] = [t0]&[t1]&[t2]&[t3] + g_nof_accumulations => c_nof_accumulations, -- integration time in symbols + g_sum_truncate => c_sum_truncate, -- when TRUE truncate (keep MS part) else resize (keep sign and LS part) + g_sum_w => c_sum_w -- typcially MM word width = 32 + ) + PORT MAP ( + clk => clk, + rst => rst, + + -- Streaming inputs + in_data => in_sosi.data(c_data_w-1 DOWNTO 0), + in_val => in_sosi.valid, + in_sync => in_sosi.sync, + + -- Accumulation outputs + sum => sum, + sum_sync => sum_sync, + sum_sop => sum_sop + ); + +END tb; diff --git a/libraries/io/aduh/tb/vhdl/tb_aduh_pll.vhd b/libraries/io/aduh/tb/vhdl/tb_aduh_pll.vhd new file mode 100644 index 0000000000..6aacfff065 --- /dev/null +++ b/libraries/io/aduh/tb/vhdl/tb_aduh_pll.vhd @@ -0,0 +1,409 @@ +------------------------------------------------------------------------------- +-- +-- Copyright (C) 2011 +-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.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, dp_lib; +USE IEEE.STD_LOGIC_1164.ALL; +USE IEEE.NUMERIC_STD.ALL; +USE common_lib.common_pkg.ALL; +USE dp_lib.dp_stream_pkg.ALL; +USE dp_lib.tb_dp_pkg.ALL; +USE work.aduh_pll_pkg.ALL; + +ENTITY tb_aduh_pll IS +END tb_aduh_pll; + +ARCHITECTURE tb OF tb_aduh_pll IS + + -- Conclusion from the c_model_rx_clk_* investigations: + -- . It appears that it is not possible to avoid the DCLK->rx_clk divide by 2 + -- phase uncertainty by releasing the CDA reset in the dp-clk domain. + CONSTANT c_model_rx_clk_phase_uncertainty_in_time : BOOLEAN := TRUE; -- When TRUE model DPA lock at different relative SCLK phase in time (0..dp_deser_factor-1) + CONSTANT c_model_rx_clk_phase_uncertainty_in_space : BOOLEAN := FALSE; -- When TRUE model DPA lock at different relative SCLK phase for each of the rx_clk (0..nof_clocks-1) + CONSTANT c_model_rx_clk_hold_reference : BOOLEAN := TRUE; -- When TRUE AND nof_clocks>1 then keep rx_clk(0) active so that rx_clk(0) is a reference + + -- Conclusion from the c_model_lvds_skew investigations: + -- . It appears that the DPA model in altera_mf.vhd does not model DPA for + -- semi static skew, e.g. skew that varies with temperature. It can only + -- model ppm drift which occurs in soft CDR (clock data recovery) mode, + -- such as needed e.g. for SGMII. In the Chip Planner the SERDES_RX that + -- implements the DPA is connected but presented as a black box. + CONSTANT c_model_lvds_skew : BOOLEAN := FALSE; -- When TRUE model DPA lock at different relative SCLK phase in time (0..dp_deser_factor-1) + + -- Conclusion from the c_model_dclk_phase investigations: + -- . Use + -- c_model_rx_clk_phase_uncertainty_in_time = TRUE; + -- c_model_rx_clk_phase_uncertainty_in_space = FALSE; + -- c_model_rx_clk_hold_reference = TRUE; + -- . To model the use_lvds_clk_rst it is necessary to deliberately start the + -- the DCLK_CD with a different phase then the DCLK_AB and then check that + -- a DCLK_RST_CD causes it to align again. This modelling is a bit fussy, + -- because using lvds_clk_rst in lvdsh.vhd also makes that the dp_pll_reset + -- gets synchronized to the dp_clk domain and that causes the + -- c_model_rx_clk_phase_uncertainty_in_time effect to become void anyway. + -- Anyway it is safe to state that using the ADC DCLK_RST is a proper + -- means to align the lvds_clk from all ADU in a system to the dp_clk. + CONSTANT c_model_dclk_phase : BOOLEAN := FALSE; -- When TRUE start DCLK_CD with different phase then DCLK_AB, else use same phase for both + + -- TYPE t_c_aduh_pll_ai IS RECORD + -- nof_sp : NATURAL; -- = 4; -- Fixed support 4 signal paths A,B,C,D, whether they contain active data depends on nof_adu + -- nof_adu : NATURAL; -- = 2; -- When 2 ADUs then use all 4 ports A,B,C,D, one ADU on ports A,B and one ADU on ports C,D, + -- -- when 1 ADU then only use ports C,D + -- nof_ports : NATURAL; -- = 2; -- Fixed 2 ADC BI ports per ADU + -- port_w : NATURAL; -- = 8; -- Fixed 8 bit ADC BI port width, the ADC sample width is also 8 bit + -- nof_ovr : NATURAL; -- = 1; -- There is 1 overflow bit per ADU, use 0 to ignore the overflow input + -- lvds_data_rate : NATURAL; -- = 800; -- The ADC sample rate is 800 Msps, so the LVDS rate is 800 Mbps per ADC BI data line, + -- use_dpa : BOOLEAN; -- = TRUE; -- When TRUE use LVDS_RX with DPA, else used fixed IOE delays and/or lvds_clk_phase instead of DPA + -- use_lvds_clk : BOOLEAN; -- = TRUE; -- When TRUE use the one or both ADC BI lvds_clk, else use the single dp_clk to capture the lvds data + -- use_lvds_clk_rst : BOOLEAN; -- = FALSE; -- When TRUE then support reset pulse to ADU to align the lvds_clk to the dp_clk, else no support + -- lvds_clk_phase : NATURAL; -- = 0; -- Use PLL phase 0 for edge aligned, phase 180 for center aligned. Only for no DPA + -- nof_clocks : NATURAL; -- = 2; -- Must be <= nof_adu + -- -- 1 --> Use ADC BI clock D or dp_clk for one or both ADU + -- -- 2 --> Use ADC BI clock A for/from ADU-AB and clock D for/from the ADU-CD + -- lvds_deser_factor : NATURAL; -- = 2; -- The ADC sampled data comes in with a DDR lvds_clk, so lvds_data_rate / 2 or + -- -- the 4 when the Data Path clock dp_clk is also used as LVDS data reference lvds_clk clock + -- dp_deser_factor : NATURAL; -- = 4; -- The Data Path clock dp_clk frequency is 200 MHz, so lvds_data_rate / 4 + -- END RECORD; + -- Uncomment one of the c_ai settings: +-- CONSTANT c_ai : t_c_aduh_pll_ai := (4, 2, 2, 8, 0, 800, FALSE, FALSE, FALSE, 0, 1, 4, 4); -- model no dpa, use dp_clk, lvds_clk_phase = 0 +-- CONSTANT c_ai : t_c_aduh_pll_ai := (4, 2, 2, 8, 0, 800, FALSE, TRUE, FALSE, 0, 2, 2, 4); -- model no dpa, use lvds_clk, lvds_clk_phase = 0 +-- CONSTANT c_ai : t_c_aduh_pll_ai := (4, 2, 2, 8, 0, 800, FALSE, TRUE, FALSE, 90, 2, 2, 4); -- model no dpa, use lvds_clk, lvds_clk_phase = 90 +-- CONSTANT c_ai : t_c_aduh_pll_ai := (4, 2, 2, 8, 0, 800, TRUE, FALSE, FALSE, 0, 1, 4, 4); -- model use dpa, use dp_clk + CONSTANT c_ai : t_c_aduh_pll_ai := (4, 2, 2, 8, 0, 800, TRUE, TRUE, FALSE, 0, 2, 2, 4); -- model use dpa, use lvds_clk +-- CONSTANT c_ai : t_c_aduh_pll_ai := (4, 2, 2, 8, 0, 800, TRUE, TRUE, TRUE, 0, 2, 2, 4); -- model use dpa, use lvds_clk, use lvds_clk_rst + + -- Conclusion on c_ai: + -- . Using DPA is preferred. + -- . First using dp_clk as LVDS_RX PLL reference is the preferred scheme. + -- . If DCLK_RST is supported by BN - ADU then using lvds_clk as LVDS_RX PLL reference with lvds_clk_rst to ADU is preferred. + -- . Not using DPA and using the lvds_clk should also be tried and verified on the BN - ADU hardware. + + CONSTANT c_sample_freq : NATURAL := c_ai.lvds_data_rate; -- Msps + CONSTANT c_sample_period : TIME := 1000000 ps / c_sample_freq; + + CONSTANT c_pll_reset_time : TIME := 20 ns; -- minimum 10 ns + CONSTANT c_measurement_period : TIME := 50 us; -- minimum depends on number of data line toggles for DPA, which can take 10-s of us for MSbit counter data, + -- because DPA lock is only achieved after about 256 toggles + + CONSTANT c_lvds_skew_zero : t_natural_arr(7 DOWNTO 0) := ( 0, 0, 0, 0, 0, 0, 0, 0); -- ps unit + CONSTANT c_lvds_skew_init : t_natural_arr(7 DOWNTO 0) := (70, 60, 50, 40, 30, 20, 10, 0); -- ps unit + CONSTANT c_lvds_skew_ovr : NATURAL := 55; -- ps unit + CONSTANT c_lvds_skew_clk : NATURAL := 35; -- ps unit + + CONSTANT c_dp_clk_period : TIME := c_ai.dp_deser_factor * c_sample_period; + CONSTANT c_dp_clk_skew : NATURAL := 335; -- ps unit, model skew between dp_clk and SCLK, both are in lock with the same reference + + CONSTANT c_ana_diff : NATURAL := 16; -- analogue offset value between the port A, B, C, D + + CONSTANT c_adc_w : NATURAL := c_ai.port_w; -- 8 bit + CONSTANT c_dp_dat_w : NATURAL := c_adc_w * c_ai.dp_deser_factor; -- 32 bit + + TYPE t_dp_data_arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(c_dp_dat_w-1 DOWNTO 0); + + -- ADC : c_ai.port_w = 8-bit + SIGNAL ANA_DAT : STD_LOGIC_VECTOR(c_ai.port_w-1 DOWNTO 0) := (OTHERS=>'0'); -- Common ADC reference data source + SIGNAL ANA_A : STD_LOGIC_VECTOR(c_ai.port_w-1 DOWNTO 0) := (OTHERS=>'0'); -- ADC port A + SIGNAL ANA_B : STD_LOGIC_VECTOR(c_ai.port_w-1 DOWNTO 0) := (OTHERS=>'0'); -- ADC port B + SIGNAL ANA_C : STD_LOGIC_VECTOR(c_ai.port_w-1 DOWNTO 0) := (OTHERS=>'0'); -- ADC port C + SIGNAL ANA_D : STD_LOGIC_VECTOR(c_ai.port_w-1 DOWNTO 0) := (OTHERS=>'0'); -- ADC port D + SIGNAL ANA_OVR : STD_LOGIC := '0'; + SIGNAL SCLK : STD_LOGIC := '1'; -- central sample clock = 800 MHz + SIGNAL DCLK_AB : STD_LOGIC; -- digital lvds clock = 400 MHz (DDR) + SIGNAL DCLK_CD : STD_LOGIC; -- digital lvds clock = 400 MHz (DDR) + SIGNAL DCLK_RST_AB : STD_LOGIC; -- synchronise digital lvds clock + SIGNAL DCLK_RST_CD : STD_LOGIC; -- synchronise digital lvds clock + SIGNAL DIG_A : STD_LOGIC_VECTOR(c_ai.port_w-1 DOWNTO 0); + SIGNAL DIG_B : STD_LOGIC_VECTOR(c_ai.port_w-1 DOWNTO 0); + SIGNAL DIG_C : STD_LOGIC_VECTOR(c_ai.port_w-1 DOWNTO 0); + SIGNAL DIG_D : STD_LOGIC_VECTOR(c_ai.port_w-1 DOWNTO 0); + SIGNAL DIG_OVR_AB : STD_LOGIC := '0'; + SIGNAL DIG_OVR_CD : STD_LOGIC := '0'; + + SIGNAL test_pattern_en : STD_LOGIC := '0'; + SIGNAL lvds_skew_di : t_natural_arr(7 DOWNTO 0) := c_lvds_skew_init; + SIGNAL lvds_skew_dq : t_natural_arr(7 DOWNTO 0) := c_lvds_skew_init; + SIGNAL lvds_skew_ovr : NATURAL := c_lvds_skew_ovr; + SIGNAL lvds_skew_dclk : NATURAL := c_lvds_skew_clk; + + -- Digital + SIGNAL dp_clk_ref : STD_LOGIC := '1'; -- digital data path clock = 200 MHz (deser factor 4); + SIGNAL dp_clk : STD_LOGIC := '1'; -- digital data path clock = 200 MHz (deser factor 4); + + -- DUT + SIGNAL dp_restart : STD_LOGIC_VECTOR(c_ai.nof_clocks-1 DOWNTO 0); + SIGNAL dp_delay_settings : t_natural_arr(func_aduh_pll_lvds_dat_w(c_ai)-1 DOWNTO 0) := (OTHERS=>0); -- ADC_BI IOE data delay settings when g_use_dpa = FALSE + SIGNAL dp_cda_settings : t_natural_arr(func_aduh_pll_lvds_dat_w(c_ai)-1 DOWNTO 0) := (OTHERS=>1); -- ADC_BI channel data alignment settings + SIGNAL dp_sosi : t_dp_sosi_arr(0 TO c_ai.nof_sp-1); -- ADC_BI ports [0:3] = [A,B,C,D] + + -- Verify + SIGNAL restart_any : STD_LOGIC := '0'; + SIGNAL verify_valid : STD_LOGIC_VECTOR(0 TO c_ai.nof_sp-1) := (OTHERS=>'0'); + SIGNAL verify_restart : STD_LOGIC_VECTOR(0 TO c_ai.nof_sp-1) := (OTHERS=>'0'); + SIGNAL verify_en : STD_LOGIC_VECTOR(0 TO c_ai.nof_sp-1) := (OTHERS=>'0'); + SIGNAL verify_en_all : STD_LOGIC := '0'; + SIGNAL verify_data : t_dp_data_arr( 0 TO c_ai.nof_sp-1); + SIGNAL prev_verify_data : t_dp_data_arr( 0 TO c_ai.nof_sp-1); + SIGNAL sl0 : STD_LOGIC := '0'; + SIGNAL sl1 : STD_LOGIC := '1'; + SIGNAL slv0 : STD_LOGIC_VECTOR(0 DOWNTO 0) := "0"; + +BEGIN + + ----------------------------------------------------------------------------- + -- ADU0 and ADU1 for BN port A,B and C,D + ----------------------------------------------------------------------------- + + -- Same analogue reference signal for all ADC, use incrementing data to ease the verification +-- ANA_DAT <= NOT ANA_DAT WHEN rising_edge(SCLK); +-- ANA_A <= ANA_DAT; +-- ANA_B <= ANA_DAT; +-- ANA_C <= ANA_DAT; +-- ANA_D <= ANA_DAT; + ANA_DAT <= INCR_UVEC(ANA_DAT, 1) WHEN rising_edge(SCLK); + ANA_A <= INCR_UVEC(ANA_DAT, 0*c_ana_diff); + ANA_B <= INCR_UVEC(ANA_DAT, 1*c_ana_diff); + ANA_C <= INCR_UVEC(ANA_DAT, 2*c_ana_diff); + ANA_D <= INCR_UVEC(ANA_DAT, 3*c_ana_diff); + ANA_OVR <= NOT ANA_OVR WHEN rising_edge(SCLK); -- simple overflow model used for both ADC + + -- Same sample clock for all ADC + SCLK <= NOT SCLK AFTER c_sample_period/2; + + -- National ADC + u_adu_AB : ENTITY work.adc08d1020 + GENERIC MAP ( + g_dclk_init_phase => 0 + ) + PORT MAP ( + AI => TO_SINT(ANA_A), + AQ => TO_SINT(ANA_B), + AOVR => ANA_OVR, + CLK => SCLK, + DCLK => DCLK_AB, + DCLK_RST => '0', + DI => DIG_A, + DQ => DIG_B, + OVR => DIG_OVR_AB, + + test_pattern_en => test_pattern_en, + lvds_skew_di => lvds_skew_di, + lvds_skew_dq => lvds_skew_dq, + lvds_skew_ovr => lvds_skew_ovr, + lvds_skew_dclk => lvds_skew_dclk + ); + + u_adu_CD : ENTITY work.adc08d1020 + GENERIC MAP ( + g_dclk_init_phase => sel_a_b(c_model_dclk_phase, 1, 0) + ) + PORT MAP ( + AI => TO_SINT(ANA_C), + AQ => TO_SINT(ANA_D), + AOVR => ANA_OVR, + CLK => SCLK, + DCLK => DCLK_CD, + DCLK_RST => DCLK_RST_CD, + DI => DIG_C, + DQ => DIG_D, + OVR => DIG_OVR_CD, + + test_pattern_en => test_pattern_en, + lvds_skew_di => lvds_skew_di, + lvds_skew_dq => lvds_skew_dq, + lvds_skew_ovr => lvds_skew_ovr, + lvds_skew_dclk => lvds_skew_dclk + ); + + ----------------------------------------------------------------------------- + -- Stimuli + ----------------------------------------------------------------------------- + + dp_clk_ref <= NOT dp_clk_ref AFTER c_dp_clk_period/2; + dp_clk <= TRANSPORT dp_clk_ref AFTER c_dp_clk_skew * 1 ps; + + -- Uncomment to try different CDA settings then the init default: +-- dp_cda_settings <= (0, 1, 2, 3, 0, 1, 2, 3, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 0, 3, 1, 3, 4, 2, 2, 0); +-- dp_cda_settings <= (0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3); +-- dp_cda_settings <= (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + + p_dp_restart : PROCESS + BEGIN + lvds_skew_di <= c_lvds_skew_zero; + lvds_skew_dq <= c_lvds_skew_zero; + + -- Wait for the ADU + dp_restart <= (OTHERS=>'1'); -- assert the LVDS RX PLL reset + WAIT UNTIL rising_edge(DCLK_AB); + WAIT UNTIL rising_edge(DCLK_CD); -- wait to ensure that the DCLKs are active + WAIT FOR 1*c_sample_period; -- set arbitrary initial phase + + -- Run several measurement with ADU + FOR I IN 0 TO 10 LOOP + WAIT FOR c_pll_reset_time; -- ensure mimimum LVDS RX PLL reset time + + IF c_model_rx_clk_phase_uncertainty_in_time = TRUE THEN + -- The next measurement will start 1 SCLK c_sample_period later to + -- verify that the fixed CDA settings are suitable. + -- It appears in simulation that for the odd I it takes much longer for + -- the DPA to lock than for the even I. + WAIT FOR I*c_sample_period; + END IF; + + IF c_model_rx_clk_phase_uncertainty_in_space = TRUE THEN + -- Wait some extra 1 SCLK c_sample_period for each PLL. The assumption + -- is that using I*c_sample_period to get a different SCLK phase for + -- the dp_restart may cause CDA misalignment between the ADUs when + -- g_use_dp_clk_for_cda_reset=FALSE in the lvdsh. In simulation the PLL + -- lock time is deterministic, so influencing the SCLK phase of + -- dp_start is a way to model the uncertainty of the real PLL lock time + -- and of the relative phase of the divided rx_clk (= dclk / 2). + -- It appears in simulation that in both cases the data output from + -- ADU0 and ADU1 gets offset by 1 sample. Using the dp_clk to release + -- the cda_reset does not help. Probably because internally it gets + -- retimed to the rx_clk domain anyway and the phase relation between + -- the rx_clk derived from ADU0 and ADU1 may differ. + FOR J IN c_ai.nof_clocks-1 DOWNTO 0 LOOP + dp_restart(J) <= '0'; -- release the LVDS RX PLL(J) reset + WAIT FOR c_sample_period; + END LOOP; + END IF; + + dp_restart <= (OTHERS=>'0'); -- release the LVDS RX PLL reset + + -- Begin of the measurement + + IF c_model_lvds_skew=TRUE THEN + WAIT FOR c_measurement_period; + lvds_skew_di <= (700, 500, 250, 140, 130, 320, 60, 50); -- ps unit + lvds_skew_dq <= (700, 500, 250, 140, 130, 320, 60, 50); -- ps unit + WAIT FOR 10*c_measurement_period; + lvds_skew_di <= c_lvds_skew_zero; + lvds_skew_dq <= c_lvds_skew_zero; + END IF; + + WAIT FOR c_measurement_period; + dp_restart <= (OTHERS=>'1'); -- assert the LVDS RX PLL reset + + IF c_model_rx_clk_hold_reference = TRUE THEN + -- Do not assert LVDS RX PLL reset for rx_clk 0, so keep this one + -- running for reference to verify the dp_sosi sample data alignment + -- with the other clock(s) when c_ai.nof_clocks > 1. + IF c_ai.nof_clocks > 1 THEN + dp_restart(0) <= '0'; + END IF; + END IF; + + -- End of the measurement + END LOOP; + WAIT; + END PROCESS; + + + ----------------------------------------------------------------------------- + -- DUT: ADUH with PLL + ----------------------------------------------------------------------------- + + -- Assume the ADU board has no skew between the ADCs. This is not too much + -- simplifcation. Any skew between the ADC will be constant and can then be + -- compensated for in a fixed, preset way. + dut : ENTITY work.aduh_pll + GENERIC MAP ( + g_ai => c_ai + ) + PORT MAP ( + -- PHY ADU Interface + + -- . ADU_AB + ADC_BI_AB_OVR => '0', + ADC_BI_A => DIG_A, + ADC_BI_B => DIG_B, + ADC_BI_A_CLK => DCLK_AB, + ADC_BI_A_CLK_RST => DCLK_RST_AB, + + -- . ADU_CD + ADC_BI_CD_OVR => '0', + ADC_BI_C => DIG_C, + ADC_BI_D => DIG_D, + ADC_BI_D_CLK => DCLK_CD, + ADC_BI_D_CLK_RST => DCLK_RST_CD, + + -- DP Interface + dp_clk => dp_clk, + + -- . Control + restart => dp_restart, + delay_settings => dp_delay_settings, + cda_settings => dp_cda_settings, + + -- . Streaming + src_out => dp_sosi -- = [0:3] = ADC_BI ports [A,B,C,D] + ); + + + ----------------------------------------------------------------------------- + -- Verify dp_sosi + -- . verify that there is valid data, i.e. that the test has run at all + -- . verify that the valid data per ADC port is incrementing + -- . verify that the valid data between the ADC ports has the correct diff (alignment) + ----------------------------------------------------------------------------- + + restart_any <= vector_or(dp_restart); + verify_en_all <= vector_and(verify_en); + + p_verify_valid : PROCESS + BEGIN + WHILE TRUE LOOP + WAIT UNTIL falling_edge(restart_any); + WAIT FOR c_measurement_period; + IF verify_en_all='0' THEN + REPORT "ADUH with PLL: No valid data, test may not be running." SEVERITY ERROR; + END IF; + END LOOP; + END PROCESS; + + -- Verify dp_sosi[0,1,2,3].data symbols compared to ADC samples from [ANA_A, ANA_B, ANA_C, ANA_D] + gen_verify_increment : FOR I IN 0 TO c_ai.nof_sp-1 GENERATE + -- Enable verify after the valid goes active and continue until valid goes low + verify_valid(I) <= dp_sosi(I).valid WHEN rising_edge(dp_clk); + verify_restart(I) <= dp_restart((I * c_ai.nof_clocks) / c_ai.nof_sp); + verify_en(I) <= verify_valid(I) AND NOT verify_restart(I); -- also and with dp_restart, because of latency in dp_sosi.valid + + -- Verify that the symbols in the data are incrementing per ADC (ready not used, empty not used) + verify_data(I) <= dp_sosi(I).data(c_dp_dat_w-1 DOWNTO 0); + proc_dp_verify_symbols(1, c_dp_dat_w, c_adc_w, dp_clk, verify_en(I), sl1, dp_sosi(I).valid, sl0, verify_data(I), slv0, prev_verify_data(I)); + END GENERATE; -- gen_verify_increment + + -- Verify the data alignment between the ADCs by checking the expected c_ana_diff offset + gen_verify_alignment : FOR I IN 1 TO c_ai.nof_sp-1 GENERATE + p_alignment : PROCESS(dp_clk) + BEGIN + IF rising_edge(dp_clk) THEN + IF verify_en_all='1' THEN + FOR J IN 0 TO c_ai.dp_deser_factor-1 LOOP + IF verify_data(I)((J+1)*c_adc_w-1 DOWNTO J*c_adc_w) /= INCR_UVEC(verify_data(I-1)((J+1)*c_adc_w-1 DOWNTO J*c_adc_w), c_ana_diff) THEN + REPORT "ADUH with PLL: Wrong alignment between ADCs." SEVERITY ERROR; + END IF; + END LOOP; + END IF; + END IF; + END PROCESS; + END GENERATE; -- gen_verify_alignment + +END tb; diff --git a/libraries/io/aduh/tb/vhdl/tb_aduh_power_sum.vhd b/libraries/io/aduh/tb/vhdl/tb_aduh_power_sum.vhd new file mode 100644 index 0000000000..2054c37779 --- /dev/null +++ b/libraries/io/aduh/tb/vhdl/tb_aduh_power_sum.vhd @@ -0,0 +1,151 @@ +------------------------------------------------------------------------------- +-- +-- Copyright (C) 2010 +-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.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, 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 common_lib.tb_common_mem_pkg.ALL; +USE common_lib.common_lfsr_sequences_pkg.ALL; +USE dp_lib.dp_stream_pkg.ALL; +USE dp_lib.tb_dp_pkg.ALL; + + +-- Usage: +-- > as 10 +-- > run 1 us +-- observe in_sosi, pwr_sum and pwr_sum_sync in wave window +-- expected pwr_sum after pwr_sync are: 0, 1240, 9176, ... + +ENTITY tb_aduh_power_sum IS + GENERIC ( + g_random_control : BOOLEAN := TRUE -- use TRUE for random stream flow control, use FALSE for initial debugging + ); +END tb_aduh_power_sum; + + +ARCHITECTURE tb OF tb_aduh_power_sum IS + + CONSTANT clk_period : TIME := 10 ns; + + CONSTANT c_rl : NATURAL := 1; + CONSTANT c_symbol_w : NATURAL := 8; + CONSTANT c_nof_symbols_per_data : NATURAL := 4; + CONSTANT c_nof_symbols_per_block : NATURAL := 8; -- nof symbols (= ADC samples) per block + + CONSTANT c_pwr_sum_truncate : BOOLEAN := TRUE; + CONSTANT c_pwr_sum_w : NATURAL := c_word_w; -- = 32 + + CONSTANT c_data_w : NATURAL := c_nof_symbols_per_data*c_symbol_w; + + CONSTANT c_nof_sync : NATURAL := 10; + CONSTANT c_nof_block_per_sync : NATURAL := 2; + CONSTANT c_nof_symbols_per_sync : NATURAL := c_nof_block_per_sync * c_nof_symbols_per_block; + + CONSTANT c_nof_accumulations : NATURAL := c_nof_symbols_per_sync; -- integration time in symbols + + SIGNAL rst : STD_LOGIC; + SIGNAL clk : STD_LOGIC := '1'; + + SIGNAL random_0 : STD_LOGIC_VECTOR(14 DOWNTO 0) := (OTHERS=>'0'); -- use different lengths to have different random sequences + + SIGNAL st_en : STD_LOGIC := '1'; + SIGNAL st_sosi : t_dp_sosi := c_dp_sosi_rst; + SIGNAL st_siso : t_dp_siso := c_dp_siso_rdy; + + SIGNAL bsn : NATURAL; + + SIGNAL in_sosi : t_dp_sosi := c_dp_sosi_rst; + + SIGNAL pwr_sum : STD_LOGIC_VECTOR(c_pwr_sum_w-1 DOWNTO 0); + SIGNAL pwr_sum_sync : STD_LOGIC; + SIGNAL pwr_sum_sop : STD_LOGIC; + +BEGIN + + clk <= NOT clk AFTER clk_period/2; + rst <= '1', '0' AFTER clk_period*5; + + -- ST domain + gen_random_control : IF g_random_control=TRUE GENERATE + random_0 <= func_common_random(random_0) WHEN rising_edge(clk); + --st_en <= NOT st_en WHEN rising_edge(clk); + --st_en <= random_0(random_0'HIGH); + END GENERATE; -- else the st_en line is always active + + p_st_stimuli : PROCESS + VARIABLE v_symbol : NATURAL := 0; + BEGIN + st_sosi <= c_dp_sosi_rst; + proc_common_wait_until_low(clk, rst); + proc_common_wait_some_cycles(clk, 5); + + -- Run some sync intervals with DSP counter data for the data field + st_sosi.sync <= '1'; -- first sync + WAIT UNTIL rising_edge(clk); + FOR I IN 0 TO c_nof_sync-1 LOOP + FOR J IN 0 TO c_nof_block_per_sync-2 LOOP -- provide sop and eop for block reference + proc_dp_gen_block_data(c_rl, TRUE, c_data_w, c_symbol_w, v_symbol, 0, 0, c_nof_symbols_per_block, 0, 0, '0', "0", clk, st_en, st_siso, st_sosi); -- no sync + v_symbol := v_symbol + c_nof_symbols_per_block; + END LOOP; + proc_dp_gen_block_data(c_rl, TRUE, c_data_w, c_symbol_w, v_symbol, 0, 0, c_nof_symbols_per_block, 0, 0, '1', "0", clk, st_en, st_siso, st_sosi); -- next sync + v_symbol := v_symbol + c_nof_symbols_per_block; + END LOOP; + + st_sosi <= c_dp_sosi_rst; + WAIT; + END PROCESS; + + -- Time stimuli + bsn <= bsn + 1 WHEN rising_edge(clk) AND st_sosi.sync='1'; + + -- Add BSN to the ST data + p_in_sosi : PROCESS(st_sosi, bsn) + BEGIN + in_sosi <= st_sosi; + in_sosi.bsn <= TO_DP_BSN(bsn); + END PROCESS; + + u_dut : ENTITY work.aduh_power_sum + GENERIC MAP ( + g_symbol_w => c_symbol_w, + g_nof_symbols_per_data => c_nof_symbols_per_data, -- big endian in_data, t0 in MSSymbol, so [h:0] = [t0]&[t1]&[t2]&[t3] + g_nof_accumulations => c_nof_accumulations, -- integration time in symbols + g_pwr_sum_truncate => c_pwr_sum_truncate, -- when TRUE truncate (keep MS part) else resize (keep sign and LS part) + g_pwr_sum_w => c_pwr_sum_w -- typcially MM word width = 32 + ) + PORT MAP ( + clk => clk, + rst => rst, + + -- Streaming inputs + in_data => in_sosi.data(c_data_w-1 DOWNTO 0), + in_val => in_sosi.valid, + in_sync => in_sosi.sync, + + -- Accumulation outputs + pwr_sum => pwr_sum, + pwr_sum_sync => pwr_sum_sync, + pwr_sum_sop => pwr_sum_sop + ); + +END tb; diff --git a/libraries/io/aduh/tb/vhdl/tb_aduh_verify.vhd b/libraries/io/aduh/tb/vhdl/tb_aduh_verify.vhd new file mode 100644 index 0000000000..2145a3f122 --- /dev/null +++ b/libraries/io/aduh/tb/vhdl/tb_aduh_verify.vhd @@ -0,0 +1,260 @@ +------------------------------------------------------------------------------- +-- +-- Copyright (C) 2011 +-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.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/>. +-- +------------------------------------------------------------------------------- + +-- Usage: +-- > as 10 +-- > run -all +-- > p_verify_res should report no errors + +LIBRARY IEEE, common_lib, dp_lib; +USE IEEE.STD_LOGIC_1164.ALL; +USE IEEE.NUMERIC_STD.ALL; +USE common_lib.common_pkg.ALL; +USE dp_lib.dp_stream_pkg.ALL; +USE work.aduh_dd_pkg.ALL; + +ENTITY tb_aduh_verify IS +END tb_aduh_verify; + +ARCHITECTURE tb OF tb_aduh_verify IS + + --TYPE t_c_aduh_dd_ai IS RECORD + -- nof_sp : NATURAL; -- = 4 + -- nof_adu : NATURAL; -- = 2 + -- nof_ports : NATURAL; -- = 2 + -- port_w : NATURAL; -- = 8 + -- dd_factor : NATURAL; -- = 2 + -- rx_factor : NATURAL; -- = 2 + -- deskew : t_c_aduh_delays; -- = (0, 0, (OTHERS=>0), (OTHERS=>0), (OTHERS=>0), (OTHERS=>0)) -- clock: a, b, data: a, b, c, d + --END RECORD; + CONSTANT c_ai : t_c_aduh_dd_ai := c_aduh_dd_ai; -- use defaults + + CONSTANT c_dp_factor : NATURAL := c_ai.rx_factor * c_ai.dd_factor; -- = 4 = 2 * 2 + + CONSTANT c_sample_period : TIME := 1250 ps; -- 800 MTps + CONSTANT c_dp_clk_period : TIME := c_sample_period*c_dp_factor; -- 200 MHz + + CONSTANT c_dp_phs_clk_step : TIME := c_dp_clk_period/32; -- the PLL can output clocks with phase shifts of 360/32 = 11.25 degrees + CONSTANT c_dp_phs_clk_period : NATURAL := 32; -- number of dp_clk periods per dp_phs_clk period + CONSTANT c_nof_dp_phs_clk : NATURAL := 1; + + SIGNAL tb_end : STD_LOGIC := '0'; + + -- Analogue + SIGNAL SCLK : STD_LOGIC := '1'; -- central sample clock = 800 MHz + SIGNAL DCLK : STD_LOGIC; -- digital lvds clock = 400 MHz (DDR) + SIGNAL DIG_A : STD_LOGIC_VECTOR(c_ai.port_w-1 DOWNTO 0); + SIGNAL DIG_B : STD_LOGIC_VECTOR(c_ai.port_w-1 DOWNTO 0); + + -- Digital streaming + SIGNAL dp_clk : STD_LOGIC := '1'; -- digital data path clock = 200 MHz (deser factor 4); + SIGNAL dp_rst : STD_LOGIC; + SIGNAL dp_phs_cnt : NATURAL := 0; + SIGNAL dp_phs_clk : STD_LOGIC := '1'; + SIGNAL dp_phs_clk_vec : STD_LOGIC_VECTOR(c_nof_dp_phs_clk-1 DOWNTO 0); + + SIGNAL aduh_sosi_arr : t_dp_sosi_arr(0 TO c_ai.nof_sp-1); + SIGNAL dp_val : STD_LOGIC; + SIGNAL dp_sosi_arr : t_dp_sosi_arr(0 TO c_ai.nof_sp-1); + + -- MM Interface + SIGNAL ab_locked : STD_LOGIC; + SIGNAL ab_stable : STD_LOGIC; + SIGNAL ab_stable_ack : STD_LOGIC := '0'; + + SIGNAL test_pattern_en : STD_LOGIC; + SIGNAL verify_ok : STD_LOGIC; -- verify that verify_res indicates OK when expected + SIGNAL verify_wrong : STD_LOGIC; -- verify that verify_res indicates ERROR when expected + + SIGNAL a_pattern_sel : NATURAL RANGE 0 TO 1 := 0; -- 0 = DI, 1 = DQ + SIGNAL a_verify_res : STD_LOGIC_VECTOR(c_ai.port_w DOWNTO 0); + SIGNAL a_verify_res_val : STD_LOGIC; + SIGNAL a_verify_res_ack : STD_LOGIC; + + SIGNAL b_pattern_sel : NATURAL RANGE 0 TO 1 := 1; -- 0 = DI, 1 = DQ + SIGNAL b_verify_res : STD_LOGIC_VECTOR(c_ai.port_w DOWNTO 0); + SIGNAL b_verify_res_val : STD_LOGIC; + SIGNAL b_verify_res_ack : STD_LOGIC; + +BEGIN + + ----------------------------------------------------------------------------- + -- ADUH_VERIFY port A and B + ----------------------------------------------------------------------------- + + -- Stimuli: + -- . tb_end test bench duration control + -- . test_pattern_en + -- . BIST restarts due to verify_res_ack + -- . dp_val to check that verify reports error when input valid goes low + test_pattern_en <= '1', '0' AFTER 5 us, '1' AFTER 6 us; + dp_val <= '1', '0' AFTER 15 us, '1' AFTER 16 us; + verify_wrong <= '0', '1' AFTER 5.5 us, '0' AFTER 6.5 us, '1' AFTER 15.5 us, '0' AFTER 16.5 us; + verify_ok <= '0', '1' AFTER 1 us, '0' AFTER 4 us, '1' AFTER 8 us , '0' AFTER 9 us, '1' AFTER 11 us , '0' AFTER 14 us, '1' AFTER 18 us; + a_verify_res_ack <= '0', '1' AFTER 7 us, '0' AFTER 7 us + c_dp_clk_period, '1' AFTER 10 us, '0' AFTER 10 us + c_dp_clk_period, '1' AFTER 17 us, '0' AFTER 17 us + c_dp_clk_period; + b_verify_res_ack <= '0', '1' AFTER 7 us, '0' AFTER 7 us + c_dp_clk_period, '1' AFTER 10 us, '0' AFTER 10 us + c_dp_clk_period, '1' AFTER 17 us, '0' AFTER 17 us + c_dp_clk_period; + tb_end <= '0', '1' AFTER 20 us; + + dp_sosi_arr <= aduh_sosi_arr WHEN dp_val='1' ELSE (OTHERS=>c_dp_sosi_rst); + + u_verify_a : ENTITY work.aduh_verify + GENERIC MAP ( + g_symbol_w => c_ai.port_w, -- = 8, fixed + g_nof_symbols_per_data => c_dp_factor -- = 4, fixed, big endian in_sosi.data, t0 in MSSymbol, so [h:0] = [t0]&[t1]&[t2]&[t3] + ) + PORT MAP ( + rst => dp_rst, + clk => dp_clk, + + -- ST input + in_sosi => dp_sosi_arr(0), + + -- Static control input (connect via MM or leave open to use default) + pattern_sel => a_pattern_sel, + verify_res => a_verify_res, + verify_res_val => a_verify_res_val, + verify_res_ack => a_verify_res_ack + ); + + u_verify_b : ENTITY work.aduh_verify + GENERIC MAP ( + g_symbol_w => c_ai.port_w, -- = 8, fixed + g_nof_symbols_per_data => c_dp_factor -- = 4, fixed, big endian in_sosi.data, t0 in MSSymbol, so [h:0] = [t0]&[t1]&[t2]&[t3] + ) + PORT MAP ( + rst => dp_rst, + clk => dp_clk, + + -- ST input + in_sosi => dp_sosi_arr(1), + + -- Static control input (connect via MM or leave open to use default) + pattern_sel => b_pattern_sel, + verify_res => b_verify_res, + verify_res_val => b_verify_res_val, + verify_res_ack => b_verify_res_ack + ); + + -- Use verify_ok to check that the verify_res is valid and indicates OK when expected + p_verify_res_ok : PROCESS(dp_clk) + BEGIN + IF rising_edge(dp_clk) THEN + IF verify_ok='1' THEN + IF a_verify_res_val='0' OR UNSIGNED(a_verify_res)/=0 THEN + REPORT "ADUH A: test pattern I error." SEVERITY ERROR; + END IF; + IF b_verify_res_val='0' OR UNSIGNED(b_verify_res)/=0 THEN + REPORT "ADUH B: test pattern Q error." SEVERITY ERROR; + END IF; + END IF; + END IF; + END PROCESS; + + -- Use verify_wrong to check that the verify_res is valid and indicates ERROR when expected + p_verify_res_wrong : PROCESS(dp_clk) + BEGIN + IF rising_edge(dp_clk) THEN + IF verify_wrong='1' THEN + IF a_verify_res_val='0' OR UNSIGNED(a_verify_res)=0 THEN + REPORT "ADUH A: test pattern I undetected error." SEVERITY ERROR; + END IF; + IF b_verify_res_val='0' OR UNSIGNED(b_verify_res)=0 THEN + REPORT "ADUH B: test pattern Q undetected error." SEVERITY ERROR; + END IF; + END IF; + END IF; + END PROCESS; + + ----------------------------------------------------------------------------- + -- ADU ADC port A,B both in test pattern mode + ----------------------------------------------------------------------------- + + -- Same sample clock for all ADC + SCLK <= (NOT SCLK) OR tb_end AFTER c_sample_period/2; + + -- National ADC + u_adc : ENTITY work.adu_half + PORT MAP ( + CLK => SCLK, + DCLK => DCLK, + DCLK_RST => '0', + DI => DIG_A, + DQ => DIG_B, + + test_pattern_en => test_pattern_en + ); + + + ----------------------------------------------------------------------------- + -- ADUH_DD using only port A,B + ----------------------------------------------------------------------------- + + dp_rst <= '1', '0' AFTER c_dp_clk_period*7; + dp_clk <= (NOT dp_clk) OR tb_end AFTER c_dp_clk_period/2; + + -- Create DP phase reference clock + p_dp_phs_clk : PROCESS(dp_clk) + BEGIN + IF c_dp_phs_clk_period=1 THEN + dp_phs_clk <= dp_clk; + ELSIF rising_edge(dp_clk) THEN + IF dp_phs_cnt MOD (c_dp_phs_clk_period/2) = 0 THEN + dp_phs_clk <= NOT dp_phs_clk; + END IF; + IF dp_phs_cnt=c_dp_phs_clk_period-1 THEN + dp_phs_cnt<=0; + ELSE + dp_phs_cnt<=dp_phs_cnt+1; + END IF; + END IF; + END PROCESS; + + gen_dp_phs_clk_vec : FOR I IN c_nof_dp_phs_clk-1 DOWNTO 0 GENERATE + dp_phs_clk_vec(I) <= TRANSPORT dp_phs_clk AFTER I*c_dp_phs_clk_step; + END GENERATE; + + u_aduh_dd : ENTITY work.aduh_dd + GENERIC MAP ( + g_ai => c_ai + ) + PORT MAP ( + -- LVDS Interface + -- . g_ai.nof_sp = 4, fixed support 4 signal paths A,B,C,D, but only use and connect A,B here + ADC_BI_A => DIG_A, + ADC_BI_B => DIG_B, + + ADC_BI_A_CLK => DCLK, + + -- MM Interface + ab_locked => ab_locked, + ab_stable => ab_stable, + ab_stable_ack => ab_stable_ack, + + -- DP Interface + dp_rst => dp_rst, + dp_clk => dp_clk, + dp_phs_clk_vec => dp_phs_clk_vec, + + -- . Streaming + src_out_arr => aduh_sosi_arr + ); + +END tb; diff --git a/libraries/io/aduh/tb/vhdl/tb_lvdsh_dd.vhd b/libraries/io/aduh/tb/vhdl/tb_lvdsh_dd.vhd new file mode 100644 index 0000000000..606238ac35 --- /dev/null +++ b/libraries/io/aduh/tb/vhdl/tb_lvdsh_dd.vhd @@ -0,0 +1,142 @@ +------------------------------------------------------------------------------- +-- +-- Copyright (C) 2011 +-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.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_lvdsh_dd IS +END tb_lvdsh_dd; + +-- Usage: +-- > as 10 +-- > run 10 us + +ARCHITECTURE tb OF tb_lvdsh_dd IS + + CONSTANT c_config_clk_period : TIME := 10 ns; + CONSTANT c_sp_clk_period : TIME := 1250 ps; -- 800 MSps sample clock + CONSTANT c_in_clk_period : TIME := c_sp_clk_period*2; -- 400 MHz double data rate clock + + CONSTANT c_in_dat_w : NATURAL := 8; + CONSTANT c_in_dat_delay_arr : t_natural_arr(0 TO c_in_dat_w-1) := array_init(0, c_in_dat_w, 1); -- nof must match g_dat_w + CONSTANT c_in_clk_delay : NATURAL := c_in_dat_delay_arr(c_in_dat_w-1) + 1; + CONSTANT c_out_dat_w : NATURAL := 2*c_in_dat_w; -- hi & lo + CONSTANT c_rx_big_endian : BOOLEAN := TRUE; + CONSTANT c_rx_factor : NATURAL := 2; -- 1, 2, 4, ... must be a power of 2 because of the mixed width FIFO + CONSTANT c_rx_fifo_size : NATURAL := 32; -- see common_fifo_dc_lock_control used in lvds_dd for comment + CONSTANT c_rx_fifo_fill : NATURAL := 16; -- see common_fifo_dc_lock_control used in lvds_dd for comment + + CONSTANT c_rx_clk_period : TIME := c_rx_factor * c_in_clk_period; -- 200 MHz data path processing clock + + SIGNAL tb_end : STD_LOGIC := '0'; + SIGNAL config_rst : STD_LOGIC := '1'; + SIGNAL config_clk : STD_LOGIC := '1'; + + SIGNAL sp_clk : STD_LOGIC := '1'; + SIGNAL in_clk : STD_LOGIC := '1'; + SIGNAL in_clk_en : STD_LOGIC; + SIGNAL in_clk_act : STD_LOGIC; + SIGNAL in_dat : STD_LOGIC_VECTOR(c_in_dat_w-1 DOWNTO 0) := (OTHERS=>'0'); + SIGNAL in_clk_rst : STD_LOGIC; + + SIGNAL out_clk : STD_LOGIC; + SIGNAL out_dat_hi : STD_LOGIC_VECTOR(c_in_dat_w-1 DOWNTO 0); + SIGNAL out_dat_lo : STD_LOGIC_VECTOR(c_in_dat_w-1 DOWNTO 0); + + SIGNAL rx_rst : STD_LOGIC := '1'; + SIGNAL rx_clk : STD_LOGIC := '1'; + SIGNAL rx_dat : STD_LOGIC_VECTOR(c_rx_factor*c_out_dat_w-1 DOWNTO 0); + SIGNAL rx_val : STD_LOGIC; + + SIGNAL rx_locked : STD_LOGIC; + SIGNAL rx_stable : STD_LOGIC; + SIGNAL rx_stable_ack : STD_LOGIC := '0'; + +BEGIN + + config_clk <= NOT config_clk OR tb_end AFTER c_config_clk_period/2; + config_rst <= '1', '0' AFTER c_config_clk_period*7; + + sp_clk <= NOT sp_clk OR tb_end AFTER c_sp_clk_period/2; + in_clk <= (NOT in_clk AND NOT in_clk_rst) OR tb_end AFTER c_in_clk_period/2; + + -- Briefly disable the in_clk to verify rx_locked and rx_stable + tb_end <= '0', '1' AFTER c_in_clk_period*10000; + in_clk_en <= '1', '0' AFTER c_in_clk_period*1000, + '1' AFTER c_in_clk_period*1100, + '0' AFTER c_in_clk_period*1200, + '1' AFTER c_in_clk_period*1700, + '0' AFTER c_in_clk_period*2300, + '1' AFTER c_in_clk_period*2400; + in_clk_act <= in_clk AND in_clk_en; + + -- Pulse rx_stable_ack to acknowledge rx_stable and re-enable it + rx_stable_ack <= '0', '1' AFTER c_rx_clk_period*100, + '0' AFTER c_rx_clk_period*101, + '1' AFTER c_rx_clk_period*1250, + '0' AFTER c_rx_clk_period*1251, + '1' AFTER c_rx_clk_period*3000, + '0' AFTER c_rx_clk_period*3001; + + rx_clk <= NOT rx_clk OR tb_end AFTER c_rx_clk_period/2; + rx_rst <= '1', '0' AFTER c_rx_clk_period*7; + + in_dat <= INCR_UVEC(in_dat, 1) WHEN rising_edge(sp_clk); + + u_dut : ENTITY work.lvdsh_dd + GENERIC MAP ( + g_in_dat_w => c_in_dat_w, + g_in_dat_delay_arr => c_in_dat_delay_arr, + g_in_clk_delay => c_in_clk_delay, + g_rx_big_endian => c_rx_big_endian, + g_rx_factor => c_rx_factor, + g_rx_fifo_size => c_rx_fifo_size, + g_rx_fifo_fill => c_rx_fifo_fill + ) + PORT MAP ( + -- PHY input delay config clock + config_rst => config_rst, + config_clk => config_clk, + + -- PHY input interface + in_clk => in_clk_act, + in_dat => in_dat, + in_clk_rst => in_clk_rst, + + -- DD domain output interface (no FIFO) + out_clk => out_clk, + out_dat_hi => out_dat_hi, + out_dat_lo => out_dat_lo, + + -- DD --> Rx domain interface at in_clk rate or g_rx_factor lower rate (via FIFO) + rx_rst => rx_rst, + rx_clk => rx_clk, + rx_dat => rx_dat, + rx_val => rx_val, + + rx_locked => rx_locked, + rx_stable => rx_stable, + rx_stable_ack => rx_stable_ack + ); + +END tb; diff --git a/libraries/io/aduh/tb/vhdl/tb_lvdsh_dd_phs4.vhd b/libraries/io/aduh/tb/vhdl/tb_lvdsh_dd_phs4.vhd new file mode 100644 index 0000000000..25d6be1dcf --- /dev/null +++ b/libraries/io/aduh/tb/vhdl/tb_lvdsh_dd_phs4.vhd @@ -0,0 +1,301 @@ +------------------------------------------------------------------------------- +-- +-- Copyright (C) 2014 +-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.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/>. +-- +------------------------------------------------------------------------------- + +-- Purpose: Test bench for lvdsh_dd_phs4 +-- Description: +-- The following generic combinations are typically applied: +-- +-- Realigned data mode (g_nof_dp_phs_clk>0): +-- g_dclk_drift g_nof_dp_phs_clk +-- g_dclk_offon g_dp_phs_clk_en_mask +-- g_dp_phs_clk_en_vary +-- 0 , TRUE 4, 16#FF#, FALSE -- default case used to verify ADU restarts +-- 0 , FALSE 4, 16#FF#, FALSE -- used by tb_tb_lvdsh_dd_phs4 to verify g_in_phase=0,1,2,3 +-- 0 , TRUE 4, 16#FF#, TRUE -- used to verify dp_phs_clk select via MM g_dp_phs_clk_en_mask control +-- 0 , TRUE 4, 0, FALSE -- used to verify phase alignment disabled for raw data via MM g_dp_phs_clk_en_mask=0 control +-- -8 ps, TRUE 4, 0, FALSE -- used to verify phase alignment disabled for raw data via MM g_dp_phs_clk_en_mask=0 control +-- +8 ps, TRUE 4, 0, FALSE -- used to verify phase alignment disabled for raw data via MM g_dp_phs_clk_en_mask=0 control +-- -2 ps, FALSE 4, 16#FF#, FALSE -- used to verify in_clk - dp_clk phase uncertainty +-- +2 ps, FALSE 4, 16#FF#, FALSE -- used to verify in_clk - dp_clk phase uncertainty +-- +-- Raw data mode (g_nof_dp_phs_clk=0): +-- g_dclk_drift g_nof_dp_phs_clk +-- g_dclk_offon g_dp_phs_clk_en_mask +-- g_dp_phs_clk_en_vary +-- 0 , TRUE 0, 16#FF#, FALSE -- used to verify ADU restarts with no phase alignment implemented so raw data only +-- 0 , TRUE 0, 16#FF#, TRUE -- used to verify that dp_phs_clk select via MM g_dp_phs_clk_en_mask control has no effect in raw data only mode +-- +8 ps, TRUE 0, 16#FF#, FALSE -- used to verify in_clk - dp_clk phase uncertainty effect on FIFO fill for raw data only +-- -8 ps, TRUE 0, 16#FF#, FALSE -- used to verify in_clk - dp_clk phase uncertainty effect on FIFO fill for raw data only +-- +-- Changes due to the tb control will cause some ASSERT ERRORs that are expected near that change. +-- +-- Usage: +-- > as 10 +-- > run -all + +LIBRARY IEEE, common_lib; +USE IEEE.std_logic_1164.ALL; +USE common_lib.common_pkg.ALL; +USE common_lib.tb_common_pkg.ALL; + +ENTITY tb_lvdsh_dd_phs4 IS + GENERIC ( + g_dclk_drift : TIME := 0 ps; -- 0 ps, use -2 ps or 2 ps to model the range of sample phase uncertainty by letting the sclk and dclk drift with respect to the dp_clk, + -- use factor 2 value because of integer divide by 2 for rising and falling edge per sclk clock period. + g_dclk_offon : BOOLEAN := TRUE; -- when TRUE switch the dclk off-on periodically, to model ADU not present or ADU restart or ADU replaced, use FALSE when g_dclk_drift/=0 ps + g_dp_phs_clk_period : NATURAL := 32; -- number of dp_clk periods per dp_phs_clk period + g_nof_dp_phs_clk : NATURAL := 4; -- nof dp_phs_clk that can be used to detect the lock, use 1 or 4 to ease interpretation of results when g_dclk_drift/=0 ps + g_dp_phs_clk_en_mask : NATURAL := 16#FF#; -- bit mask to individually enable or disable a dp_phs_clk in range [g_nof_dp_phs_clk-1:0] + g_dp_phs_clk_en_vary : BOOLEAN := FALSE; -- use FALSE to use g_dp_phs_clk_en_mask, else use TRUE to vary g_dp_phs_clk_en_vec (assuming g_nof_dp_phs_clk>1) + g_in_phase : NATURAL := 0 -- 0:3 + ); +END tb_lvdsh_dd_phs4; + +ARCHITECTURE tb OF tb_lvdsh_dd_phs4 IS + + CONSTANT c_dd_factor : NATURAL := 2; + CONSTANT c_rx_factor : NATURAL := 2; + CONSTANT c_wb_factor : NATURAL := c_dd_factor*c_rx_factor; + + CONSTANT c_sim : BOOLEAN := TRUE; + CONSTANT c_tb_duration : NATURAL := sel_a_b(g_dclk_drift/=0 ps OR g_dclk_offon=TRUE, 1000, 10); -- nof tb intervals for tb duration + CONSTANT c_tb_init : NATURAL := sel_a_b(g_dclk_drift/=0 ps OR g_dclk_offon=TRUE, 10, 10); -- nof tb intervals for tb init before verify_en + + CONSTANT c_clk_factor : NATURAL := 100; -- slow down dclk to improve modelling dclk phase uncertainy with g_dclk_drift, which is minimal 2 ps + CONSTANT c_ref_s_clk_period : TIME := c_clk_factor*1.25 ns; -- 800 MHz sample clock for dp_sample_dat monitor + CONSTANT c_adc_s_clk_period : TIME := c_ref_s_clk_period + g_dclk_drift; -- 800 MHz single data rate ADC sample clock with optional drift + CONSTANT c_ref_dp_clk_period : TIME := c_ref_s_clk_period*c_wb_factor; -- 200 MHz data clock for Data Path processing + CONSTANT c_dp_phs_clk_step : TIME := c_ref_dp_clk_period/32; -- the PLL can output clocks with phase shifts of 360/32 = 11.25 degrees + CONSTANT c_dp_phs_clk_en_mask : STD_LOGIC_VECTOR(g_nof_dp_phs_clk-1 DOWNTO 0) := TO_UVEC(g_dp_phs_clk_en_mask, g_nof_dp_phs_clk); + + CONSTANT c_interval : NATURAL := 180; -- some unit tb interval + CONSTANT c_on_interval : TIME := (c_tb_duration * c_interval / 3 + 3) * c_ref_s_clk_period; + CONSTANT c_off_interval : TIME := (c_tb_duration * c_interval / 3 + 7) * c_ref_s_clk_period; + --CONSTANT c_off_interval : TIME := 1 * c_ref_s_clk_period; -- if multiple of c_wb_factor=4 then the off period is only noticed by the FIFO running empty + + CONSTANT c_rl : NATURAL := 1; + CONSTANT c_init : NATURAL := 0; + CONSTANT c_in_dat_w : NATURAL := 8; + CONSTANT c_dp_dat_w : NATURAL := c_wb_factor*c_in_dat_w; + CONSTANT c_dp_phase_even2 : BOOLEAN := g_in_phase MOD 2 = 0; -- TRUE for g_in_phase=0,2 and FALSE for g_in_phase=1,3 + CONSTANT c_dp_phase_even4 : BOOLEAN := g_in_phase < 2; -- TRUE for g_in_phase=0,1 and FALSE for g_in_phase=2,3 + CONSTANT c_dp_phase_latency : NATURAL := 1; -- account for internal pipeling to be able to compare dp_sample_phase with the in_sample_phase + + SIGNAL tb_g_dclk_drift : TIME := g_dclk_drift; + SIGNAL tb_g_dclk_offon : BOOLEAN := g_dclk_offon; + SIGNAL tb_g_in_phase : NATURAL := g_in_phase; + + SIGNAL tb_end : STD_LOGIC := '0'; + SIGNAL rst : STD_LOGIC := '1'; + SIGNAL adc_s_clk : STD_LOGIC := '1'; + SIGNAL adc_d_clk : STD_LOGIC := '1'; + SIGNAL adc_d_clk_off : STD_LOGIC := '0'; + SIGNAL adc_d_clkg : STD_LOGIC := '1'; -- = adc_d_clk gated with adc_d_clk_off + SIGNAL ref_s_clk : STD_LOGIC := '1'; + SIGNAL ref_d_clk : STD_LOGIC := '1'; + SIGNAL ref_dp_clk : STD_LOGIC := '1'; + SIGNAL dp_clk_vec : STD_LOGIC_VECTOR(c_wb_factor-1 DOWNTO 0); + SIGNAL dp_clk : STD_LOGIC; + SIGNAL dp_phs_cnt : NATURAL := 0; + SIGNAL dp_phs_clk : STD_LOGIC := '1'; + SIGNAL dp_phs_clk_vec : STD_LOGIC_VECTOR(g_nof_dp_phs_clk-1 DOWNTO 0); + SIGNAL dp_phs_clk_en_vec : STD_LOGIC_VECTOR(g_nof_dp_phs_clk-1 DOWNTO 0) := c_dp_phs_clk_en_mask; + SIGNAL ready : STD_LOGIC := '1'; + SIGNAL verify_en : STD_LOGIC := '0'; + SIGNAL verify_phase_en : STD_LOGIC := '0'; + SIGNAL verify_sample_phase_en : STD_LOGIC := '0'; + SIGNAL verify_data_en : STD_LOGIC := '0'; + SIGNAL cnt_en : STD_LOGIC := '1'; + + SIGNAL in_dat : STD_LOGIC_VECTOR(c_in_dat_w-1 DOWNTO 0) := (OTHERS=>'0'); + SIGNAL in_dat_lo : STD_LOGIC_VECTOR(c_in_dat_w-1 DOWNTO 0); + SIGNAL in_val : STD_LOGIC; + SIGNAL dp_dat_lo : STD_LOGIC_VECTOR(c_in_dat_w-1 DOWNTO 0); + SIGNAL dp_dat_diff : STD_LOGIC_VECTOR(c_in_dat_w-1 DOWNTO 0); + SIGNAL dp_dat : STD_LOGIC_VECTOR(c_dp_dat_w-1 DOWNTO 0); + SIGNAL dp_val : STD_LOGIC := '1'; + SIGNAL dp_sample_dat : STD_LOGIC_VECTOR(c_in_dat_w-1 DOWNTO 0); + SIGNAL prev_dp_sample_dat : STD_LOGIC_VECTOR(c_in_dat_w-1 DOWNTO 0); + + SIGNAL in_sample_phase : NATURAL; + SIGNAL dp_sample_phase : NATURAL; + + SIGNAL dp_status : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0); -- extra status information for debug + SIGNAL dp_phs_locked : STD_LOGIC; + SIGNAL dp_word_locked : STD_LOGIC; + SIGNAL dp_word_stable : STD_LOGIC; + SIGNAL dp_word_stable_ack : STD_LOGIC; + +BEGIN + + -- ADU clocking with optional on/off and drift + adc_s_clk <= NOT adc_s_clk OR tb_end AFTER c_adc_s_clk_period/2; + adc_d_clk <= NOT adc_d_clk WHEN rising_edge(adc_s_clk); + adc_d_clkg <= adc_d_clk OR adc_d_clk_off WHEN c_dp_phase_even2=TRUE ELSE NOT adc_d_clk OR adc_d_clk_off; + + p_on_off : PROCESS + BEGIN + IF g_dclk_offon=FALSE THEN + adc_d_clk_off <= '0'; WAIT; + ELSE + adc_d_clk_off <= '0'; IF tb_end='1' THEN WAIT; ELSE WAIT FOR c_on_interval; END IF; + adc_d_clk_off <= '1'; IF tb_end='1' THEN WAIT; ELSE WAIT FOR c_off_interval; END IF; + END IF; + END PROCESS; + + -- TB ideal clocking + ref_s_clk <= NOT ref_s_clk OR tb_end AFTER c_ref_s_clk_period/2; + ref_d_clk <= NOT ref_d_clk WHEN rising_edge(ref_s_clk); + ref_dp_clk <= NOT ref_dp_clk WHEN rising_edge(ref_d_clk); + + gen_dp_clk_vec : FOR I IN 0 TO c_wb_factor-1 GENERATE + dp_clk_vec(I)<= TRANSPORT ref_dp_clk AFTER (REAL(I) + 0.5)*c_ref_s_clk_period; + END GENERATE; + + dp_clk <= dp_clk_vec(0) WHEN c_dp_phase_even4=TRUE ELSE dp_clk_vec(2); -- actually c_dp_phase_even4=TRUE can not truely be modeled from the outside in this tb + --dp_clk <= dp_clk_vec(0); + + -- Create DP phase reference clock + p_dp_phs_clk : PROCESS(dp_clk) + BEGIN + IF g_dp_phs_clk_period=1 THEN + dp_phs_clk <= dp_clk; + ELSIF rising_edge(dp_clk) THEN + IF dp_phs_cnt MOD (g_dp_phs_clk_period/2) = 0 THEN + dp_phs_clk <= NOT dp_phs_clk; + END IF; + IF dp_phs_cnt=g_dp_phs_clk_period-1 THEN + dp_phs_cnt<=0; + ELSE + dp_phs_cnt<=dp_phs_cnt+1; + END IF; + END IF; + END PROCESS; + + gen_dp_phs_clk_vec : FOR I IN g_nof_dp_phs_clk-1 DOWNTO 0 GENERATE + dp_phs_clk_vec(I) <= TRANSPORT dp_phs_clk AFTER I*c_dp_phs_clk_step; + END GENERATE; + + gen_tb_dp_phs_clk_en : IF g_dp_phs_clk_en_vary=TRUE GENERATE + dp_phs_clk_en_vec <= TO_UVEC(255, g_nof_dp_phs_clk), + TO_UVEC( 1, g_nof_dp_phs_clk) AFTER 10 ms, + TO_UVEC( 64, g_nof_dp_phs_clk) AFTER 20 ms, + TO_UVEC( 16, g_nof_dp_phs_clk) AFTER 30 ms, + TO_UVEC( 8, g_nof_dp_phs_clk) AFTER 40 ms, + TO_UVEC( 2, g_nof_dp_phs_clk) AFTER 50 ms, + TO_UVEC( 32, g_nof_dp_phs_clk) AFTER 60 ms, + TO_UVEC( 4, g_nof_dp_phs_clk) AFTER 70 ms, + TO_UVEC(128, g_nof_dp_phs_clk) AFTER 80 ms, + TO_UVEC( 14, g_nof_dp_phs_clk) AFTER 90 ms; + END GENERATE; + + rst <= '1', '0' AFTER 16*c_ref_s_clk_period; + + proc_common_gen_pulse(1, c_interval, '1', rst, dp_clk, dp_word_stable_ack); + + -- Stimuli data + p_stimuli : PROCESS + BEGIN + proc_common_wait_some_cycles(dp_clk, c_interval*c_tb_init); + verify_en <= '1'; + + proc_common_wait_some_cycles(dp_clk, c_interval*c_tb_duration); + tb_end <= '1'; + WAIT; + END PROCESS; + + proc_common_gen_data(c_rl, c_init, rst, adc_s_clk, cnt_en, ready, in_dat, in_val); + + in_dat_lo <= in_dat WHEN rising_edge(dp_clk); + dp_dat_lo <= dp_dat(4*c_in_dat_w-1 DOWNTO 3*c_in_dat_w) WHEN rising_edge(dp_clk); + dp_dat_diff <= SUB_UVEC(in_dat_lo, dp_dat_lo) WHEN rising_edge(dp_clk); + in_sample_phase <= TO_UINT( in_dat_lo ) MOD c_wb_factor WHEN rising_edge(dp_clk); + dp_sample_phase <= TO_UINT(INCR_UVEC(dp_dat_lo, c_dp_phase_latency)) MOD c_wb_factor WHEN rising_edge(dp_clk); + + -- Verify data + verify_data_en <= verify_en OR dp_word_locked; + verify_phase_en <= verify_en WHEN g_dclk_offon=FALSE ELSE '0'; + verify_sample_phase_en <= verify_en WHEN g_dclk_drift=0 ps AND g_dp_phs_clk_en_mask/=0 ELSE '0'; + + proc_common_verify_data(c_rl, ref_s_clk, verify_data_en, ready, dp_val, dp_sample_dat, prev_dp_sample_dat); + + p_verify_phase : PROCESS(dp_clk) + BEGIN + IF rising_edge(dp_clk) THEN + IF verify_phase_en='1' THEN + ASSERT dp_phs_locked ='1' REPORT "Unexpected dp phase detected" SEVERITY ERROR; + END IF; + IF verify_sample_phase_en='1' THEN + ASSERT dp_sample_phase=in_sample_phase REPORT "Unexpected dp_sample_phase" SEVERITY ERROR; + END IF; + END IF; + END PROCESS; + + -- DUT (device under test) + u_lvdsh_dd_phs4 : ENTITY work.lvdsh_dd_phs4 + GENERIC MAP ( + g_sim => c_sim, + g_wb_factor => c_wb_factor, + g_dp_phs_clk_period => g_dp_phs_clk_period, + g_nof_dp_phs_clk => g_nof_dp_phs_clk, + g_in_dat_w => c_in_dat_w + ) + PORT MAP ( + -- PHY input interface + in_clk => adc_d_clkg, + in_dat => in_dat, + + -- DD --> Rx domain interface at adc_d_clk rate or g_dp_factor lower rate (via FIFO) + dp_rst => rst, + dp_clk => dp_clk, + dp_phs_clk_vec => dp_phs_clk_vec, + dp_phs_clk_en_vec => dp_phs_clk_en_vec, + dp_dat => dp_dat, + dp_val => dp_val, + + -- Rx status monitor + out_status => dp_status, + out_phs_locked => dp_phs_locked, + out_word_locked => dp_word_locked, + out_word_stable => dp_word_stable, + out_word_stable_ack => dp_word_stable_ack + ); + + u_wb_data_scope : ENTITY common_lib.common_wideband_data_scope + GENERIC MAP ( + g_sim => TRUE, + g_wideband_factor => c_wb_factor, + g_wideband_big_endian => TRUE, + g_dat_w => c_in_dat_w + ) + PORT MAP ( + -- Sample clock + SCLK => ref_s_clk, + + -- Streaming input data + in_data => dp_dat, + in_val => dp_val, + + -- Scope output samples + out_dat => dp_sample_dat + ); + +END tb; diff --git a/libraries/io/aduh/tb/vhdl/tb_lvdsh_dd_wb4.vhd b/libraries/io/aduh/tb/vhdl/tb_lvdsh_dd_wb4.vhd new file mode 100644 index 0000000000..490388a674 --- /dev/null +++ b/libraries/io/aduh/tb/vhdl/tb_lvdsh_dd_wb4.vhd @@ -0,0 +1,230 @@ +------------------------------------------------------------------------------- +-- +-- Copyright (C) 2014 +-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.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/>. +-- +------------------------------------------------------------------------------- + +-- Purpose: Test bench for lvdsh_dd_wb4 +-- Description: +-- Usage: +-- > as 10 +-- > run -all + +LIBRARY IEEE, common_lib; +USE IEEE.std_logic_1164.ALL; +USE common_lib.common_pkg.ALL; +USE common_lib.tb_common_pkg.ALL; + +ENTITY tb_lvdsh_dd_wb4 IS + GENERIC ( + g_dclk_drift : TIME := 0 ps; -- 0 ps, use -2 ps or 2 ps to model the range of sample phase uncertainty by letting the sclk and dclk drift with respect to the dp_clk, + -- use factor 2 value because of integer divide by 2 for rising and falling edge per sclk clock period. + g_dclk_offon : BOOLEAN := TRUE; -- when TRUE switch the dclk off-on periodically, to model ADU not present or ADU restart or ADU replaced + g_in_phase : NATURAL := 1 -- 0:3 + ); +END tb_lvdsh_dd_wb4; + +ARCHITECTURE tb OF tb_lvdsh_dd_wb4 IS + + CONSTANT c_sim : BOOLEAN := TRUE; + CONSTANT c_tb_duration : NATURAL := sel_a_b(g_dclk_drift/=0 ps OR g_dclk_offon=TRUE, 1000, 10); -- nof tb intervals for tb duration + CONSTANT c_tb_init : NATURAL := sel_a_b(g_dclk_drift/=0 ps OR g_dclk_offon=TRUE, 50, 5); -- nof tb intervals for tb init before verify_en + CONSTANT c_interval : NATURAL := 180; -- some unit tb interval + CONSTANT c_offon_interval : NATURAL := c_interval*c_tb_duration/13; + + CONSTANT c_dd_factor : NATURAL := 2; + CONSTANT c_rx_factor : NATURAL := 2; + CONSTANT c_wb_factor : NATURAL := c_dd_factor*c_rx_factor; + CONSTANT c_clk_factor : NATURAL := 100; -- slow down dclk to improve modelling dclk phase uncertainy with g_dclk_drift, which is minimal 2 ps + + CONSTANT c_sclk_period : TIME := c_clk_factor*1.25 ns + g_dclk_drift; -- 800 MHz single data rate ADC sample clock with optional drift + CONSTANT c_dp_sclk_period : TIME := c_clk_factor*1.25 ns; -- 800 MHz sample clock for dp_sample_dat monitor + CONSTANT c_dp_clk_period : TIME := c_clk_factor*5 ns; -- 200 MHz data clock for Data Path processing + CONSTANT c_dp_clk_delay : TIME := (0.0 + 0.05)*c_dp_clk_period; -- = 0 degrees + --CONSTANT c_dp_clk_delay : TIME := (0.125 + 0.05)*c_dp_clk_period; -- = 45 degrees + --CONSTANT c_dp_clk_delay : TIME := (0.25 + 0.05)*c_dp_clk_period; -- = 90 degrees + --CONSTANT c_dp_clk_delay : TIME := (0.375 + 0.05)*c_dp_clk_period; -- = 135 degrees + --CONSTANT c_dp_clk_delay : TIME := (0.5 + 0.05)*c_dp_clk_period; -- = 180 degrees + --CONSTANT c_dp_clk_delay : TIME := (0.625 + 0.05)*c_dp_clk_period; -- = 225 degrees + --CONSTANT c_dp_clk_delay : TIME := (0.75 + 0.05)*c_dp_clk_period; -- = 270 degrees + --CONSTANT c_dp_clk_delay : TIME := (0.875 + 0.05)*c_dp_clk_period; -- = 315 degrees + + CONSTANT c_rl : NATURAL := 1; + CONSTANT c_init : NATURAL := 0; + CONSTANT c_in_dat_w : NATURAL := 8; + CONSTANT c_dp_dat_w : NATURAL := c_wb_factor*c_in_dat_w; + + SIGNAL tb_g_dclk_drift : TIME := g_dclk_drift; + SIGNAL tb_g_dclk_offon : BOOLEAN := g_dclk_offon; + SIGNAL tb_g_in_phase : NATURAL := g_in_phase; + + SIGNAL tb_end : STD_LOGIC := '0'; + SIGNAL rst : STD_LOGIC := '1'; + SIGNAL s_clk : STD_LOGIC := '1'; + SIGNAL d_clk : STD_LOGIC := '1'; + SIGNAL d_clk_off : STD_LOGIC := '0'; + SIGNAL d_clk_rst : STD_LOGIC; + SIGNAL dp_clk : STD_LOGIC := '1'; + SIGNAL dp_clkq : STD_LOGIC; + SIGNAL dp_clk_dly : STD_LOGIC; + SIGNAL dp_clkq_dly : STD_LOGIC; + SIGNAL dp_sclk : STD_LOGIC := '1'; + SIGNAL ready : STD_LOGIC := '1'; + SIGNAL verify_en : STD_LOGIC := '0'; + SIGNAL verify_phase_en : STD_LOGIC := '0'; + SIGNAL verify_data_en : STD_LOGIC := '0'; + SIGNAL cnt_en : STD_LOGIC := '1'; + + SIGNAL in_dat : STD_LOGIC_VECTOR(c_in_dat_w-1 DOWNTO 0) := (OTHERS=>'0'); + SIGNAL in_val : STD_LOGIC; + SIGNAL dp_dat : STD_LOGIC_VECTOR(c_dp_dat_w-1 DOWNTO 0); + SIGNAL dp_val : STD_LOGIC := '1'; + SIGNAL dp_sample_dat : STD_LOGIC_VECTOR(c_in_dat_w-1 DOWNTO 0); + SIGNAL prev_dp_sample_dat : STD_LOGIC_VECTOR(c_in_dat_w-1 DOWNTO 0); + + SIGNAL dp_sync_phase : NATURAL; + SIGNAL dp_status : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0); -- extra status information for debug + SIGNAL dp_locked : STD_LOGIC; + SIGNAL dp_stable : STD_LOGIC; + SIGNAL dp_stable_ack : STD_LOGIC; + +BEGIN + + d_clk_off <= NOT d_clk_off OR tb_end AFTER c_offon_interval * c_dp_clk_period WHEN g_dclk_offon=TRUE; + + s_clk <= NOT s_clk OR tb_end AFTER c_sclk_period/2; + dp_sclk <= NOT dp_sclk OR tb_end AFTER c_dp_sclk_period/2; + + p_dclk_divider : PROCESS + BEGIN + IF rst='1' OR d_clk_off='1' THEN + d_clk <= '1'; + WAIT UNTIL rising_edge(s_clk); + ELSE + CASE g_in_phase IS + WHEN 0|2 => d_clk <= '1'; WAIT UNTIL rising_edge(s_clk); + d_clk <= '0'; WAIT UNTIL rising_edge(s_clk); + WHEN 1|3 => d_clk <= '0'; WAIT UNTIL rising_edge(s_clk); + d_clk <= '1'; WAIT UNTIL rising_edge(s_clk); + WHEN OTHERS => NULL; + END CASE; + END IF; + END PROCESS; + + p_dp_clk_divider : PROCESS + BEGIN + IF rst='1' THEN + dp_clk <= '1'; + WAIT UNTIL rising_edge(s_clk); + ELSE + dp_clk <= '1'; WAIT UNTIL rising_edge(dp_sclk); + dp_clk <= '1'; WAIT UNTIL rising_edge(dp_sclk); + dp_clk <= '0'; WAIT UNTIL rising_edge(dp_sclk); + dp_clk <= '0'; WAIT UNTIL rising_edge(dp_sclk); + END IF; + END PROCESS; + + rst <= '1', '0' AFTER 3*c_dp_clk_period; + + proc_common_gen_pulse(1, c_interval, '1', rst, dp_clk, dp_stable_ack); + + -- Stimuli data + p_stimuli : PROCESS + BEGIN + proc_common_wait_some_cycles(dp_clk, c_interval*c_tb_init); + IF g_dclk_drift=0 ps THEN + verify_en <= '1'; + END IF; + + proc_common_wait_some_cycles(dp_clk, c_interval*c_tb_duration); + + proc_common_wait_some_cycles(dp_clk, c_interval); + tb_end <= '1'; + WAIT; + END PROCESS; + + proc_common_gen_data(c_rl, c_init, rst, s_clk, cnt_en, ready, in_dat, in_val); + + -- Verify data + verify_data_en <= verify_en OR dp_locked; + verify_phase_en <= verify_en; + + proc_common_verify_data(c_rl, dp_sclk, verify_data_en, ready, dp_val, dp_sample_dat, prev_dp_sample_dat); + + p_verify_phase : PROCESS(dp_clk) + BEGIN + IF rising_edge(dp_clk) THEN + IF verify_phase_en='1' THEN + ASSERT dp_sync_phase=g_in_phase OR dp_sync_phase=4+g_in_phase REPORT "Unexpected dp_sync_phase" SEVERITY ERROR; + END IF; + END IF; + END PROCESS; + + -- DUT (device under test) + dp_clkq <= TRANSPORT dp_clk AFTER c_dp_clk_period/4; + dp_clk_dly <= TRANSPORT dp_clk AFTER c_dp_clk_delay; + dp_clkq_dly <= TRANSPORT dp_clk_dly AFTER c_dp_clk_period/4; + + u_lvdsh_dd_wb4 : ENTITY work.lvdsh_dd_wb4 + GENERIC MAP ( + g_sim => c_sim, + g_sim_phase => g_in_phase, + g_wb_factor => c_wb_factor, + g_in_dat_w => c_in_dat_w + ) + PORT MAP ( + -- PHY input interface + in_clk_rst => d_clk_rst, + in_clk => d_clk, + in_dat => in_dat, + + -- DD --> Rx domain interface at d_clk rate or g_dp_factor lower rate (via FIFO) + dp_rst => rst, + dp_clk => dp_clk_dly, + dp_clkq => dp_clkq_dly, + dp_dat => dp_dat, + dp_val => dp_val, + + -- Rx status monitor + dp_sync_phase => dp_sync_phase, + dp_status => dp_status, + dp_locked => dp_locked, + dp_stable => dp_stable, + dp_stable_ack => dp_stable_ack + ); + + u_wb_data_scope : ENTITY common_lib.common_wideband_data_scope + GENERIC MAP ( + g_sim => TRUE, + g_wideband_factor => c_wb_factor, + g_wideband_big_endian => TRUE, + g_dat_w => c_in_dat_w + ) + PORT MAP ( + -- Sample clock + SCLK => dp_sclk, + + -- Streaming input data + in_data => dp_dat, + in_val => dp_val, + + -- Scope output samples + out_dat => dp_sample_dat + ); + +END tb; diff --git a/libraries/io/aduh/tb/vhdl/tb_mms_aduh_quad.vhd b/libraries/io/aduh/tb/vhdl/tb_mms_aduh_quad.vhd new file mode 100644 index 0000000000..bf3451cbed --- /dev/null +++ b/libraries/io/aduh/tb/vhdl/tb_mms_aduh_quad.vhd @@ -0,0 +1,338 @@ +------------------------------------------------------------------------------- +-- +-- Copyright (C) 2011 +-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.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/>. +-- +------------------------------------------------------------------------------- + +-- Usage: +-- > as 10 +-- > run 20 us +-- > p_verify_res should report no errors + +LIBRARY IEEE, common_lib, dp_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_pkg.ALL; +USE common_lib.tb_common_mem_pkg.ALL; +USE dp_lib.dp_stream_pkg.ALL; +USE work.aduh_dd_pkg.ALL; + +ENTITY tb_mms_aduh_quad IS +END tb_mms_aduh_quad; + +ARCHITECTURE tb OF tb_mms_aduh_quad IS + + --TYPE t_c_aduh_dd_ai IS RECORD + -- nof_sp : NATURAL; -- = 4 + -- nof_adu : NATURAL; -- = 2 + -- nof_ports : NATURAL; -- = 2 + -- port_w : NATURAL; -- = 8 + -- dd_factor : NATURAL; -- = 2 + -- rx_factor : NATURAL; -- = 2 + -- deskew : t_c_aduh_delays; -- = (0, 0, (OTHERS=>0), (OTHERS=>0), (OTHERS=>0), (OTHERS=>0)) -- clock: a, b, data: a, b, c, d + --END RECORD; + CONSTANT c_ai : t_c_aduh_dd_ai := c_aduh_dd_ai; -- use defaults + + CONSTANT c_dp_factor : NATURAL := c_ai.rx_factor * c_ai.dd_factor; -- = 4 = 2 * 2 + + CONSTANT c_sample_period : TIME := 1250 ps; -- 800 MTps + CONSTANT c_dp_clk_period : TIME := c_sample_period*c_dp_factor; -- 200 MHz + CONSTANT c_mm_clk_period : TIME := 20 ns; -- 50 MHz + + CONSTANT c_aduh_verify_val_bi : NATURAL := 12; + CONSTANT c_aduh_verify_res_hi : NATURAL := 8; + CONSTANT c_aduh_verify_res_mask : NATURAL := 2**(c_aduh_verify_res_hi+1) - 1; + + CONSTANT c_dp_phs_clk_step : TIME := c_dp_clk_period/32; -- the PLL can output clocks with phase shifts of 360/32 = 11.25 degrees + CONSTANT c_dp_phs_clk_period : NATURAL := 32; -- number of dp_clk periods per dp_phs_clk period + CONSTANT c_nof_dp_phs_clk : NATURAL := 1; + + PROCEDURE proc_verify_bist_expect_ok(aduh_a_verify, aduh_b_verify, aduh_c_verify, aduh_d_verify : STD_LOGIC_VECTOR) IS + BEGIN + ASSERT aduh_a_verify(c_aduh_verify_val_bi)='1' REPORT "ADU-A bist did not run" SEVERITY ERROR; + ASSERT aduh_b_verify(c_aduh_verify_val_bi)='1' REPORT "ADU-B bist did not run" SEVERITY ERROR; + ASSERT aduh_c_verify(c_aduh_verify_val_bi)='1' REPORT "ADU-C bist did not run" SEVERITY ERROR; + ASSERT aduh_d_verify(c_aduh_verify_val_bi)='1' REPORT "ADU-D bist did not run" SEVERITY ERROR; + ASSERT TO_UINT(aduh_a_verify(c_aduh_verify_res_hi DOWNTO 0))=0 REPORT "ADU-A bist went wrong" SEVERITY ERROR; + ASSERT TO_UINT(aduh_b_verify(c_aduh_verify_res_hi DOWNTO 0))=0 REPORT "ADU-B bist went wrong" SEVERITY ERROR; + ASSERT TO_UINT(aduh_c_verify(c_aduh_verify_res_hi DOWNTO 0))=0 REPORT "ADU-C bist went wrong" SEVERITY ERROR; + ASSERT TO_UINT(aduh_d_verify(c_aduh_verify_res_hi DOWNTO 0))=0 REPORT "ADU-D bist went wrong" SEVERITY ERROR; + END; + + PROCEDURE proc_verify_bist_expect_errors(aduh_a_verify, aduh_b_verify, aduh_c_verify, aduh_d_verify : STD_LOGIC_VECTOR) IS + BEGIN + ASSERT aduh_a_verify(c_aduh_verify_val_bi)='1' REPORT "ADU-A bist did not run" SEVERITY ERROR; + ASSERT aduh_b_verify(c_aduh_verify_val_bi)='1' REPORT "ADU-B bist did not run" SEVERITY ERROR; + ASSERT aduh_c_verify(c_aduh_verify_val_bi)='1' REPORT "ADU-C bist did not run" SEVERITY ERROR; + ASSERT aduh_d_verify(c_aduh_verify_val_bi)='1' REPORT "ADU-D bist did not run" SEVERITY ERROR; + ASSERT TO_UINT(aduh_a_verify(c_aduh_verify_res_hi DOWNTO 0))=c_aduh_verify_res_mask REPORT "ADU-A bist error detection went wrong" SEVERITY ERROR; + ASSERT TO_UINT(aduh_b_verify(c_aduh_verify_res_hi DOWNTO 0))=c_aduh_verify_res_mask REPORT "ADU-B bist error detection went wrong" SEVERITY ERROR; + ASSERT TO_UINT(aduh_c_verify(c_aduh_verify_res_hi DOWNTO 0))=c_aduh_verify_res_mask REPORT "ADU-C bist error detection went wrong" SEVERITY ERROR; + ASSERT TO_UINT(aduh_d_verify(c_aduh_verify_res_hi DOWNTO 0))=c_aduh_verify_res_mask REPORT "ADU-D bist error detection went wrong" SEVERITY ERROR; + END; + + SIGNAL tb_end : STD_LOGIC := '0'; + + -- Analogue + SIGNAL SCLK : STD_LOGIC := '1'; -- central sample clock = 800 MHz + SIGNAL DCLK_AB : STD_LOGIC; -- digital lvds clock = 400 MHz (DDR) + SIGNAL DCLK_CD : STD_LOGIC; -- digital lvds clock = 400 MHz (DDR) + SIGNAL DIG_A : STD_LOGIC_VECTOR(c_ai.port_w-1 DOWNTO 0); + SIGNAL DIG_B : STD_LOGIC_VECTOR(c_ai.port_w-1 DOWNTO 0); + SIGNAL DIG_C : STD_LOGIC_VECTOR(c_ai.port_w-1 DOWNTO 0); + SIGNAL DIG_D : STD_LOGIC_VECTOR(c_ai.port_w-1 DOWNTO 0); + + -- Digital streaming + SIGNAL dp_clk : STD_LOGIC := '1'; -- digital data path clock = 200 MHz (deser factor 4); + SIGNAL dp_rst : STD_LOGIC; + SIGNAL dp_phs_cnt : NATURAL := 0; + SIGNAL dp_phs_clk : STD_LOGIC := '1'; + SIGNAL dp_phs_clk_vec : STD_LOGIC_VECTOR(c_nof_dp_phs_clk-1 DOWNTO 0); + + SIGNAL aduh_sosi_arr : t_dp_sosi_arr(0 TO c_ai.nof_sp-1); + + -- MM Interface + SIGNAL mm_clk : STD_LOGIC := '1'; -- MM control clock = 50 MHz + SIGNAL mm_rst : STD_LOGIC; + + -- MM aduh quad register + SIGNAL aduh_ab_locked : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0); + SIGNAL aduh_cd_locked : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0); + SIGNAL aduh_a_verify : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0); + SIGNAL aduh_b_verify : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0); + SIGNAL aduh_c_verify : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0); + SIGNAL aduh_d_verify : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0); + + SIGNAL reg_mosi : t_mem_mosi := c_mem_mosi_rst; -- ADUH locked status and pattern verify for two half ADUs so 4 ADC inputs A, B, C and D + SIGNAL reg_miso : t_mem_miso; + + SIGNAL test_pattern_en : STD_LOGIC; + SIGNAL state : STRING(1 TO 8) := "INIT "; + +BEGIN + + dp_rst <= '1', '0' AFTER c_dp_clk_period*7; + dp_clk <= (NOT dp_clk) OR tb_end AFTER c_dp_clk_period/2; + + mm_rst <= '1', '0' AFTER c_mm_clk_period*7; + mm_clk <= (NOT mm_clk) OR tb_end AFTER c_mm_clk_period/2; + + -- Create DP phase reference clock + p_dp_phs_clk : PROCESS(dp_clk) + BEGIN + IF c_dp_phs_clk_period=1 THEN + dp_phs_clk <= dp_clk; + ELSIF rising_edge(dp_clk) THEN + IF dp_phs_cnt MOD (c_dp_phs_clk_period/2) = 0 THEN + dp_phs_clk <= NOT dp_phs_clk; + END IF; + IF dp_phs_cnt=c_dp_phs_clk_period-1 THEN + dp_phs_cnt<=0; + ELSE + dp_phs_cnt<=dp_phs_cnt+1; + END IF; + END IF; + END PROCESS; + + gen_dp_phs_clk_vec : FOR I IN c_nof_dp_phs_clk-1 DOWNTO 0 GENERATE + dp_phs_clk_vec(I) <= TRANSPORT dp_phs_clk AFTER I*c_dp_phs_clk_step; + END GENERATE; + + ---------------------------------------------------------------------------- + -- Stimuli for MM REG slave port + ---------------------------------------------------------------------------- + + p_mm_reg_stimuli : PROCESS + BEGIN + reg_mosi <= c_mem_mosi_rst; + test_pattern_en <= '1'; + + ---------------------------------------------------------------------------- + -- Initialisations + ---------------------------------------------------------------------------- + + proc_common_wait_until_low(mm_clk, mm_rst); + proc_common_wait_some_cycles(mm_clk, 10); + + -- Read aduh locked status for AB, CD + proc_common_wait_some_cycles(mm_clk, 10); + state <= "LOCKED "; + proc_mem_mm_bus_rd(0, mm_clk, reg_mosi); proc_mem_mm_bus_rd_latency(c_mem_reg_rd_latency, mm_clk); aduh_ab_locked <= reg_miso.rddata(31 DOWNTO 0); + proc_mem_mm_bus_rd(1, mm_clk, reg_mosi); proc_mem_mm_bus_rd_latency(c_mem_reg_rd_latency, mm_clk); aduh_cd_locked <= reg_miso.rddata(31 DOWNTO 0); + proc_common_wait_some_cycles(mm_clk, 1); + ASSERT TO_UINT(aduh_ab_locked)=3 REPORT "ADU-AB in not locked" SEVERITY ERROR; + ASSERT TO_UINT(aduh_cd_locked)=3 REPORT "ADU-CD in not locked" SEVERITY ERROR; + + ---------------------------------------------------------------------------- + -- Expect aduh BIST OK for A, B, C, D + ---------------------------------------------------------------------------- + proc_common_wait_some_cycles(mm_clk, 10); + state <= "BIST_OK "; + proc_mem_mm_bus_rd(2, mm_clk, reg_mosi); proc_mem_mm_bus_rd_latency(c_mem_reg_rd_latency, mm_clk); aduh_a_verify <= reg_miso.rddata(31 DOWNTO 0); + proc_mem_mm_bus_rd(3, mm_clk, reg_mosi); proc_mem_mm_bus_rd_latency(c_mem_reg_rd_latency, mm_clk); aduh_b_verify <= reg_miso.rddata(31 DOWNTO 0); + proc_mem_mm_bus_rd(4, mm_clk, reg_mosi); proc_mem_mm_bus_rd_latency(c_mem_reg_rd_latency, mm_clk); aduh_c_verify <= reg_miso.rddata(31 DOWNTO 0); + proc_mem_mm_bus_rd(5, mm_clk, reg_mosi); proc_mem_mm_bus_rd_latency(c_mem_reg_rd_latency, mm_clk); aduh_d_verify <= reg_miso.rddata(31 DOWNTO 0); + proc_common_wait_some_cycles(mm_clk, 1); + proc_verify_bist_expect_ok(aduh_a_verify, aduh_b_verify, aduh_c_verify, aduh_d_verify); + + test_pattern_en <= '0'; + -- Read aduh locked status for AB, CD + proc_common_wait_some_cycles(mm_clk, 10); + proc_mem_mm_bus_rd(0, mm_clk, reg_mosi); proc_mem_mm_bus_rd_latency(c_mem_reg_rd_latency, mm_clk); aduh_ab_locked <= reg_miso.rddata(31 DOWNTO 0); + proc_mem_mm_bus_rd(1, mm_clk, reg_mosi); proc_mem_mm_bus_rd_latency(c_mem_reg_rd_latency, mm_clk); aduh_cd_locked <= reg_miso.rddata(31 DOWNTO 0); + proc_common_wait_some_cycles(mm_clk, 1); + ASSERT TO_UINT(aduh_ab_locked)=3 REPORT "ADU-AB in not locked" SEVERITY ERROR; + ASSERT TO_UINT(aduh_cd_locked)=3 REPORT "ADU-CD in not locked" SEVERITY ERROR; + + ---------------------------------------------------------------------------- + -- Expect aduh BIST errors for A, B, C, D + ---------------------------------------------------------------------------- + proc_common_wait_some_cycles(mm_clk, 10); + state <= "BIST_ERR"; + proc_mem_mm_bus_rd(2, mm_clk, reg_mosi); proc_mem_mm_bus_rd_latency(c_mem_reg_rd_latency, mm_clk); aduh_a_verify <= reg_miso.rddata(31 DOWNTO 0); + proc_mem_mm_bus_rd(3, mm_clk, reg_mosi); proc_mem_mm_bus_rd_latency(c_mem_reg_rd_latency, mm_clk); aduh_b_verify <= reg_miso.rddata(31 DOWNTO 0); + proc_mem_mm_bus_rd(4, mm_clk, reg_mosi); proc_mem_mm_bus_rd_latency(c_mem_reg_rd_latency, mm_clk); aduh_c_verify <= reg_miso.rddata(31 DOWNTO 0); + proc_mem_mm_bus_rd(5, mm_clk, reg_mosi); proc_mem_mm_bus_rd_latency(c_mem_reg_rd_latency, mm_clk); aduh_d_verify <= reg_miso.rddata(31 DOWNTO 0); + proc_common_wait_some_cycles(mm_clk, 1); + proc_verify_bist_expect_errors(aduh_a_verify, aduh_b_verify, aduh_c_verify, aduh_d_verify); + + ---------------------------------------------------------------------------- + -- Expect aduh BIST errors for A, B, C, D + ---------------------------------------------------------------------------- + proc_common_wait_some_cycles(mm_clk, 10); + test_pattern_en <= '1'; + proc_common_wait_some_cycles(mm_clk, 100); + state <= "BIST_ERR"; + proc_mem_mm_bus_rd(2, mm_clk, reg_mosi); proc_mem_mm_bus_rd_latency(c_mem_reg_rd_latency, mm_clk); aduh_a_verify <= reg_miso.rddata(31 DOWNTO 0); + proc_mem_mm_bus_rd(3, mm_clk, reg_mosi); proc_mem_mm_bus_rd_latency(c_mem_reg_rd_latency, mm_clk); aduh_b_verify <= reg_miso.rddata(31 DOWNTO 0); + proc_mem_mm_bus_rd(4, mm_clk, reg_mosi); proc_mem_mm_bus_rd_latency(c_mem_reg_rd_latency, mm_clk); aduh_c_verify <= reg_miso.rddata(31 DOWNTO 0); + proc_mem_mm_bus_rd(5, mm_clk, reg_mosi); proc_mem_mm_bus_rd_latency(c_mem_reg_rd_latency, mm_clk); aduh_d_verify <= reg_miso.rddata(31 DOWNTO 0); + proc_common_wait_some_cycles(mm_clk, 1); + proc_verify_bist_expect_errors(aduh_a_verify, aduh_b_verify, aduh_c_verify, aduh_d_verify); + + + ---------------------------------------------------------------------------- + -- Expect aduh BIST OK for A, B, C, D + ---------------------------------------------------------------------------- + proc_common_wait_some_cycles(mm_clk, 10); + state <= "BIST_OK "; + proc_mem_mm_bus_rd(2, mm_clk, reg_mosi); proc_mem_mm_bus_rd_latency(c_mem_reg_rd_latency, mm_clk); aduh_a_verify <= reg_miso.rddata(31 DOWNTO 0); + proc_mem_mm_bus_rd(3, mm_clk, reg_mosi); proc_mem_mm_bus_rd_latency(c_mem_reg_rd_latency, mm_clk); aduh_b_verify <= reg_miso.rddata(31 DOWNTO 0); + proc_mem_mm_bus_rd(4, mm_clk, reg_mosi); proc_mem_mm_bus_rd_latency(c_mem_reg_rd_latency, mm_clk); aduh_c_verify <= reg_miso.rddata(31 DOWNTO 0); + proc_mem_mm_bus_rd(5, mm_clk, reg_mosi); proc_mem_mm_bus_rd_latency(c_mem_reg_rd_latency, mm_clk); aduh_d_verify <= reg_miso.rddata(31 DOWNTO 0); + proc_common_wait_some_cycles(mm_clk, 1); + proc_verify_bist_expect_ok(aduh_a_verify, aduh_b_verify, aduh_c_verify, aduh_d_verify); + + proc_common_wait_some_cycles(mm_clk, 10); + tb_end <= '1'; + WAIT; + END PROCESS; + + + ------------------------------------------------------------------------------ + -- ADUH_QUAD for ADC port [ABCD] + ------------------------------------------------------------------------------ + + u_dut : ENTITY work.mms_aduh_quad + GENERIC MAP ( + -- General + g_cross_clock_domain => TRUE, + -- ADC Interface + g_ai => c_aduh_dd_ai + ) + PORT MAP ( + -- ADC Interface + -- . ADU_AB + ADC_BI_A => DIG_A, + ADC_BI_B => DIG_B, + ADC_BI_A_CLK => DCLK_AB, + ADC_BI_A_CLK_RST => OPEN, + + -- . ADU_CD + ADC_BI_C => DIG_A, + ADC_BI_D => DIG_D, + ADC_BI_D_CLK => DCLK_CD, + ADC_BI_D_CLK_RST => OPEN, + + -- MM clock domain + mm_rst => mm_rst, + mm_clk => mm_clk, + + reg_mosi => reg_mosi, + reg_miso => reg_miso, + + -- Streaming clock domain + dp_rst => dp_rst, + dp_clk => dp_clk, + dp_phs_clk_vec => dp_phs_clk_vec, + + -- . data + aduh_sosi_arr => aduh_sosi_arr + ); + + -- Scope in Wave Window for debug purpose + u_scope : ENTITY work.aduh_quad_scope + GENERIC MAP ( + -- General + g_sim => TRUE, + -- ADC Interface + g_ai => c_aduh_dd_ai + ) + PORT MAP ( + -- Sample clock + SCLK => SCLK, + + -- Streaming samples (can be from ADU or from internal WG) + sp_sosi_arr => aduh_sosi_arr + ); + + + ------------------------------------------------------------------------------ + -- ADU-[AB, CD] ADC ports both in test pattern mode + ------------------------------------------------------------------------------ + + -- Same sample clock for all ADC + SCLK <= (NOT SCLK) OR tb_end AFTER c_sample_period/2; + + -- National ADC + u_adc_ab : ENTITY work.adu_half + PORT MAP ( + CLK => SCLK, + DCLK => DCLK_AB, + DCLK_RST => '0', + DI => DIG_A, + DQ => DIG_B, + + test_pattern_en => test_pattern_en + ); + + -- National ADC + u_adc_cd : ENTITY work.adu_half + PORT MAP ( + CLK => SCLK, + DCLK => DCLK_CD, + DCLK_RST => '0', + DI => DIG_C, + DQ => DIG_D, + + test_pattern_en => test_pattern_en + ); + +END tb; diff --git a/libraries/io/aduh/tb/vhdl/tb_tb_lvdsh_dd_phs4.vhd b/libraries/io/aduh/tb/vhdl/tb_tb_lvdsh_dd_phs4.vhd new file mode 100644 index 0000000000..bfc33a1397 --- /dev/null +++ b/libraries/io/aduh/tb/vhdl/tb_tb_lvdsh_dd_phs4.vhd @@ -0,0 +1,53 @@ +------------------------------------------------------------------------------- +-- +-- Copyright (C) 2010 +-- 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; +USE IEEE.std_logic_1164.ALL; + + +ENTITY tb_tb_lvdsh_dd_phs4 IS +END tb_tb_lvdsh_dd_phs4; + + +ARCHITECTURE tb OF tb_tb_lvdsh_dd_phs4 IS + + CONSTANT c_dp_phs_clk_period : NATURAL := 32; + +BEGIN + + -- > as 3 + -- > run -all + + -- g_dclk_drift : TIME := 0 ps; -- 0 ps, use -2 ps or 2 ps to model the range of sample phase uncertainty by letting the sclk and dclk drift with respect to the dp_clk, + -- g_dclk_offon : BOOLEAN := TRUE; -- when TRUE switch the dclk off-on periodically, to model ADU not present or ADU restart or ADU replaced + -- g_dp_phs_clk_period : NATURAL := 32; -- number of dp_clk periods per dp_phs_clk period + -- g_nof_dp_phs_clk : NATURAL := 1; -- nof dp_phs_clk that can be used to detect the lock + -- g_dp_phs_clk_en_mask : NATURAL := 16#FF#; -- bit mask to indiviually enable or disable a dp_phs_clk in range [g_nof_dp_phs_clk-1:0] + -- g_dp_phs_clk_en_vary : BOOLEAN := FALSE; -- use FALSE to use g_dp_phs_clk_en_mask, else use TRUE to vary g_dp_phs_clk_en_vec (assuming g_nof_dp_phs_clk>1) + -- g_in_phase : NATURAL := 1 -- 0:3 + + u_phase_0 : ENTITY work.tb_lvdsh_dd_phs4 GENERIC MAP (0 ps, FALSE, c_dp_phs_clk_period, 1, 16#FF#, FALSE, 0); + u_phase_1 : ENTITY work.tb_lvdsh_dd_phs4 GENERIC MAP (0 ps, FALSE, c_dp_phs_clk_period, 1, 16#FF#, FALSE, 1); + u_phase_2 : ENTITY work.tb_lvdsh_dd_phs4 GENERIC MAP (0 ps, FALSE, c_dp_phs_clk_period, 1, 16#FF#, FALSE, 2); + u_phase_3 : ENTITY work.tb_lvdsh_dd_phs4 GENERIC MAP (0 ps, FALSE, c_dp_phs_clk_period, 1, 16#FF#, FALSE, 3); + +END tb; diff --git a/libraries/io/aduh/tb/vhdl/tb_tb_lvdsh_dd_wb4.vhd b/libraries/io/aduh/tb/vhdl/tb_tb_lvdsh_dd_wb4.vhd new file mode 100644 index 0000000000..21399729c7 --- /dev/null +++ b/libraries/io/aduh/tb/vhdl/tb_tb_lvdsh_dd_wb4.vhd @@ -0,0 +1,46 @@ +------------------------------------------------------------------------------- +-- +-- Copyright (C) 2010 +-- 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; +USE IEEE.std_logic_1164.ALL; + + +ENTITY tb_tb_lvdsh_dd_wb4 IS +END tb_tb_lvdsh_dd_wb4; + + +ARCHITECTURE tb OF tb_tb_lvdsh_dd_wb4 IS +BEGIN + + -- > as 3 + -- > run -all + + -- g_dclk_drift : TIME := 0 ps; -- 0 ps, use -2 ps or 2 ps to model the range of sample phase uncertainty by letting the sclk and dclk drift with respect to the dp_clk, + -- g_dclk_offon : BOOLEAN := TRUE; -- when TRUE switch the dclk off-on periodically, to model ADU not present or ADU restart or ADU replaced + -- g_in_phase : NATURAL := 1 -- 0:3 + + u_phase_0 : ENTITY work.tb_lvdsh_dd_wb4 GENERIC MAP (0 ps, FALSE, 0); + u_phase_1 : ENTITY work.tb_lvdsh_dd_wb4 GENERIC MAP (0 ps, FALSE, 1); + u_phase_2 : ENTITY work.tb_lvdsh_dd_wb4 GENERIC MAP (0 ps, FALSE, 2); + u_phase_3 : ENTITY work.tb_lvdsh_dd_wb4 GENERIC MAP (0 ps, FALSE, 3); + +END tb; -- GitLab