x400: sim: Move testbenches to sim folder

Original-commit: c0f9496d59947f8c9411b28d63d0c8e6244102a0
This commit is contained in:
Wade Fife
2021-06-17 08:16:59 -05:00
parent fcfc6bf387
commit 77a66a4de4
13 changed files with 0 additions and 0 deletions
+91
View File
@@ -0,0 +1,91 @@
#
# Copyright 2021 Ettus Research, a National Instruments Brand
#
# SPDX-License-Identifier: LGPL-3.0-or-later
#
#-------------------------------------------------
# Top-of-Makefile
#-------------------------------------------------
# Define BASE_DIR to point to the "top" dir. Note:
# UHD_FPGA_DIR must be passed into this Makefile.
BASE_DIR = ../../..
# Include viv_sim_preample after defining BASE_DIR
include $(BASE_DIR)/../tools/make/viv_sim_preamble.mak
#-------------------------------------------------
# Design Specific
#-------------------------------------------------
# Define part using PART_ID (<device>/<package>/<speedgrade>)
ARCH = zynquplusRFSOC
PART_ID = xczu28dr/ffvg1517/-1/e
# Include makefiles and sources for the DUT and its dependencies
include $(BASE_DIR)/../lib/fifo/Makefile.srcs
include $(BASE_DIR)/../lib/axi/Makefile.srcs
include $(BASE_DIR)/../lib/control/Makefile.srcs
DESIGN_SRCS += $(abspath \
$(FIFO_SRCS) \
$(AXI_SRCS) \
$(CONTROL_LIB_SRCS) \
)
include ../common/Makefile.srcs
include ../100m/Makefile.srcs
include ../200m/Makefile.srcs
include ../400m/Makefile.srcs
DESIGN_SRCS += $(abspath \
../../regmap/PkgRFDC_REGS_REGMAP.vhd \
$(RF_COMMON_SRCS) \
$(RF_100M_SRCS) \
$(RF_200M_SRCS) \
$(RF_400M_SRCS) \
)
#-------------------------------------------------
# IP Specific
#-------------------------------------------------
# If simulation contains IP, define the IP_DIR and point
# it to the base level IP directory
IP_DIR = $(BASE_DIR)/x400/ip
LIB_IP_DIR = $(BASE_DIR)/../lib/ip
# Include makefiles and sources for all IP components
# *after* defining the IP_DIR
#
# These TBs don't use any IP yet :)
#-------------------------------------------------
# Testbench Specific
#-------------------------------------------------
include $(BASE_DIR)/../sim/general/Makefile.srcs
# Define only one top-level module
SIM_TOP = rf_all_tb
# Simulation runtime in microseconds
SIM_RUNTIME_US = 1000
SIM_SRCS = \
$(abspath tb_adc_gearbox_2x1.vhd ) \
$(abspath tb_adc_gearbox_2x4.vhd ) \
$(abspath tb_adc_gearbox_8x4.vhd ) \
$(abspath tb_capture_sysref.vhd ) \
$(abspath tb_dac_gearbox_12x8.vhd ) \
$(abspath tb_dac_gearbox_4x2.vhd ) \
$(abspath tb_dac_gearbox_6x12.vhd ) \
$(abspath tb_ddc_400m_saturate.vhd ) \
$(abspath tb_duc_400m_saturate.vhd ) \
$(abspath tb_rf_nco_reset.vhd ) \
$(abspath tb_rf_reset_controller.vhd) \
$(abspath rf_all_tb.sv ) \
#-------------------------------------------------
# Bottom-of-Makefile
#-------------------------------------------------
# Include all simulator specific makefiles here
# Each should define a unique target to simulate
# e.g. xsim, vsim, etc and a common "clean" target
include $(BASE_DIR)/../tools/make/viv_simulator.mak
+57
View File
@@ -0,0 +1,57 @@
//
// Copyright 2021 Ettus Research, a National Instruments Brand
//
// SPDX-License-Identifier: LGPL-3.0-or-later
//
// Module: rf_all_tb
//
// Description:
//
// Top-level testbench for X400 RF components. This instantiates all the RF
// testbenches.
//
module rf_all_tb;
`include "test_exec.svh"
import PkgTestExec::*;
tb_adc_gearbox_2x1 tb_adc_gearbox_2x1_i ();
tb_adc_gearbox_2x4 tb_adc_gearbox_2x4_i ();
tb_adc_gearbox_8x4 tb_adc_gearbox_8x4_i ();
tb_capture_sysref tb_capture_sysref_i ();
tb_dac_gearbox_12x8 tb_dac_gearbox_12x8_i ();
tb_dac_gearbox_4x2 tb_dac_gearbox_4x2_i ();
tb_dac_gearbox_6x12 tb_dac_gearbox_6x12_i ();
tb_ddc_400m_saturate tb_ddc_400m_saturate_i ();
tb_duc_400m_saturate tb_duc_400m_saturate_i ();
tb_rf_nco_reset tb_rf_nco_reset_i ();
tb_rf_reset_controller tb_rf_reset_controller_i ();
initial begin
test.start_tb("rf_all_tb", 1ms);
test.start_test("Run RF TBs");
forever begin
#100ns;
if (
tb_adc_gearbox_2x1_i.StopSim &&
tb_adc_gearbox_2x4_i.StopSim &&
tb_adc_gearbox_8x4_i.StopSim &&
tb_capture_sysref_i.StopSim &&
tb_dac_gearbox_12x8_i.StopSim &&
tb_dac_gearbox_4x2_i.StopSim &&
tb_dac_gearbox_6x12_i.StopSim &&
tb_ddc_400m_saturate_i.StopSim &&
tb_duc_400m_saturate_i.StopSim &&
tb_rf_nco_reset_i.StopSim &&
tb_rf_reset_controller_i.StopSim
) break;
end
test.end_test();
// If they all stop before the timeout, and there are no errors, then we
// assume everything passed.
test.end_tb();
end
endmodule : rf_all_tb
+186
View File
@@ -0,0 +1,186 @@
--
-- Copyright 2021 Ettus Research, a National Instruments Brand
--
-- SPDX-License-Identifier: LGPL-3.0-or-later
--
-- Module: tb_adc_gearbox_2x1
--
-- Description:
--
-- Self-checking testbench for adc_gearbox_2x1.
--
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity tb_adc_gearbox_2x1 is
end tb_adc_gearbox_2x1;
architecture RTL of tb_adc_gearbox_2x1 is
component adc_gearbox_2x1
port (
clk1x : in std_logic;
reset_n_1x : in std_logic;
adc_q_in_1x : in std_logic_vector(31 downto 0);
adc_i_in_1x : in std_logic_vector(31 downto 0);
valid_in_1x : in std_logic;
enable_1x : in std_logic;
clk2x : in std_logic;
swap_iq_2x : in std_logic;
adc_out_2x : out std_logic_vector(31 downto 0);
valid_out_2x : out std_logic);
end component;
signal cDataCheckNxtLo, cDataCheckLo : std_logic_vector(31 downto 0);
signal cDataCheckNxtHi, cDataCheckHi1, cDataCheckHi2 : std_logic_vector(31 downto 0);
signal adc_i_in_1x : std_logic_vector(31 downto 0);
signal adc_out_2x : std_logic_vector(31 downto 0);
signal adc_q_in_1x : std_logic_vector(31 downto 0);
signal enable_1x : std_logic;
signal reset_n_1x : std_logic;
signal swap_iq_2x : std_logic;
signal valid_in_1x : std_logic;
signal valid_out_2x : std_logic;
signal StopSim : boolean;
constant kPer : time := 10 ns;
signal Clk : std_logic := '1';
signal Clk2x : std_logic := '1';
procedure ClkWait(X : positive := 1) is
begin
for i in 1 to X loop
wait until rising_edge(Clk);
end loop;
end procedure ClkWait;
begin
Clk <= not Clk after kPer/2 when not StopSim else '0';
Clk2x <= not Clk2x after kPer/4 when not StopSim else '0';
dut: adc_gearbox_2x1
port map (
clk1x => Clk,
reset_n_1x => reset_n_1x,
adc_q_in_1x => adc_q_in_1x,
adc_i_in_1x => adc_i_in_1x,
valid_in_1x => valid_in_1x,
enable_1x => enable_1x,
clk2x => Clk2x,
swap_iq_2x => swap_iq_2x,
adc_out_2x => adc_out_2x,
valid_out_2x => valid_out_2x
);
main: process
begin
swap_iq_2x <= '0';
valid_in_1x <= '0';
enable_1x <= '0';
reset_n_1x <= '0';
ClkWait(5);
reset_n_1x <= '1';
ClkWait(5);
-- Ensure the outputs are quiet.
ClkWait(20);
assert valid_out_2x'stable(kPer*20) and valid_out_2x = '0'
report "valid not stable at de-asserted at startup"
severity error;
assert adc_out_2x'stable(kPer*20) and (adc_out_2x = x"00000000")
report "data not stable at zero at startup"
severity error;
-- Valid asserted, Enable asserted, Enable de-asserted, Valid de-asserted.
ClkWait(10);
valid_in_1x <= '1';
ClkWait(10);
enable_1x <= '1';
ClkWait(110);
assert valid_out_2x'stable(kPer*100) and valid_out_2x = '1'
report "valid not stable at asserted"
severity error;
ClkWait(10);
enable_1x <= '0';
ClkWait(10);
valid_in_1x <= '0';
ClkWait(110);
assert valid_out_2x'stable(kPer*100) and valid_out_2x = '0'
report "valid not stable at de-asserted"
severity error;
-- Enable asserted, Valid asserted, Enable de-asserted, Valid de-asserted.
ClkWait(10);
enable_1x <= '1';
ClkWait(10);
valid_in_1x <= '1';
ClkWait(110);
assert valid_out_2x'stable(kPer*100) and valid_out_2x = '1'
report "valid not stable at asserted"
severity error;
ClkWait(10);
enable_1x <= '0';
ClkWait(10);
valid_in_1x <= '0';
ClkWait(110);
assert valid_out_2x'stable(kPer*100) and valid_out_2x = '0'
report "valid not stable at de-asserted"
severity error;
StopSim <= true;
wait;
end process;
driver: process(Clk)
variable tempQdata : integer := 1;
variable tempIdata : integer := 128;
begin
if rising_edge(Clk) then
adc_q_in_1x <= std_logic_vector(to_unsigned(tempQdata+1,16)) & std_logic_vector(to_unsigned(tempQdata, 16));
adc_i_in_1x <= std_logic_vector(to_unsigned(tempIdata+1,16)) & std_logic_vector(to_unsigned(tempIdata, 16));
cDataCheckNxtLo <= std_logic_vector(to_unsigned(tempQdata,16)) & std_logic_vector(to_unsigned(tempIdata, 16));
cDataCheckNxtHi <= std_logic_vector(to_unsigned(tempQdata+1,16)) & std_logic_vector(to_unsigned(tempIdata+1,16));
tempQdata := tempQdata+2;
tempIdata := tempIdata+2;
end if;
end process;
checker: process(Clk2x)
variable tempout : integer := 1;
variable ExpectedData : std_logic_vector(31 downto 0) := (others => '0');
begin
if falling_edge(Clk2x) then
if Clk = '1' then
ExpectedData := cDataCheckLo;
else
ExpectedData := cDataCheckHi2;
end if;
if valid_out_2x = '1' then
assert adc_out_2x = ExpectedData
report "ADC data out mismatch from expected"
severity error;
tempout := tempout +1;
end if;
cDataCheckLo <= cDataCheckNxtLo;
cDataCheckHi1 <= cDataCheckNxtHi;
cDataCheckHi2 <= cDataCheckHi1;
end if;
end process;
end RTL;
+197
View File
@@ -0,0 +1,197 @@
--
-- Copyright 2021 Ettus Research, a National Instruments Brand
--
-- SPDX-License-Identifier: LGPL-3.0-or-later
--
-- Module: tb_adc_gearbox_2x4
--
-- Description:
--
-- Self-checking testbench for the gearbox that expands the data width from 2
-- SPC to 4 SPC.
--
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity tb_adc_gearbox_2x4 is
end tb_adc_gearbox_2x4;
architecture RTL of tb_adc_gearbox_2x4 is
component adc_gearbox_2x4
port (
Clk1x : in std_logic;
Clk3x : in std_logic;
ac1Reset_n : in std_logic;
ac3Reset_n : in std_logic;
c3DataIn : in std_logic_vector(95 downto 0);
c3DataValidIn : in std_logic;
c1DataOut : out std_logic_vector(191 downto 0);
c1DataValidOut : out std_logic);
end component;
signal aTestReset : boolean;
signal ac1Reset_n : std_logic := '1';
signal ac3Reset_n : std_logic := '1';
signal c3DataIn : std_logic_vector( 95 downto 0) := (others => '0');
signal c3DataValidIn : std_logic := '0';
signal c1ExpectedData : std_logic_vector(191 downto 0) := (others => '0');
signal c1DataOut : std_logic_vector(191 downto 0) := (others => '0');
signal c1DataValidOut : std_logic;
signal StopSim : boolean;
constant kPer : time := 12 ns;
signal Clk1x : std_logic := '1';
signal Clk3x : std_logic := '1';
procedure Clk3xWait(X : positive := 1) is
begin
for i in 1 to X loop
wait until rising_edge(Clk3x);
end loop;
end procedure Clk3xWait;
procedure Clk1xWait(X : positive := 1) is
begin
for i in 1 to X loop
wait until rising_edge(Clk1x);
end loop;
end procedure Clk1xWait;
begin
Clk1x <= not Clk1x after kPer/2 when not StopSim else '0';
Clk3x <= not Clk3x after kPer/6 when not StopSim else '0';
dut: adc_gearbox_2x4
port map (
Clk1x => Clk1x,
Clk3x => Clk3x,
ac1Reset_n => ac1Reset_n,
ac3Reset_n => ac3Reset_n,
c3DataIn => c3DataIn,
c3DataValidIn => c3DataValidIn,
c1DataOut => c1DataOut,
c1DataValidOut => c1DataValidOut
);
main: process
procedure PhaseTest(WaitCycles : positive := 1) is
begin
-- Stop data generation by asserting this reset.
aTestReset <= true;
Clk1xWait;
ac1Reset_n <= '0';
ac3Reset_n <= '0';
Clk1xWait;
ac1Reset_n <= '1';
ac3Reset_n <= '1';
-- This wait is in Clk3x domain. This is used to change phase in which
-- data valid is asserted with respect to Clk3x and Clk1x rising edge.
-- Wait an additional 12 Clk3x cycles for the output data valid to be
-- de-asserted.
Clk3xWait(WaitCycles+12);
-- De-asserting test reset will start data generation.
aTestReset <= false;
-- Wait for a random time before we stop the test.
Clk3xWait(1000);
end procedure;
begin
-- Change phase between Clk1x and Clk3x. See details in the DUT.
-- The wait in each phase test is used to move the de-assertion of data
-- generation logic reset. By doing this, we can change data valid
-- assertion phase between Clk3x and Clk1x.
-- p0.
PhaseTest(1);
-- p1
PhaseTest(2);
-- p2.
PhaseTest(6);
-- Stop simulation
StopSim <= true;
wait;
end process;
-- Process to generate data to the DUT.
driver: process(Clk3x, aTestReset)
variable tempQdata : integer := 1;
variable tempIdata : integer := 128;
variable dataCount : integer := 0;
begin
if aTestReset then
tempQdata := 1;
tempIdata := 128;
dataCount := 0;
c3DataIn <= (others => '0');
c3DataValidIn <= '0';
elsif rising_edge(Clk3x) then
if dataCount < 2 then
c3DataIn <= "0000000" & std_logic_vector(to_unsigned(tempQdata+1,17)) &
"0000000" & std_logic_vector(to_unsigned(tempIdata+1,17)) &
"0000000" & std_logic_vector(to_unsigned(tempQdata+0,17)) &
"0000000" & std_logic_vector(to_unsigned(tempIdata+0,17));
dataCount := dataCount + 1;
c3DataValidIn <= '1';
tempQdata := tempQdata +2;
tempIdata := tempIdata +2;
elsif dataCount = 2 then
c3DataIn <= (others => '0');
dataCount := 0;
c3DataValidIn <= '0';
end if;
end if;
end process;
-- Process to generate expected data that is used to verify the DUT output.
expected_data: process(Clk1x)
variable tempQdata : integer := 1;
variable tempIdata : integer := 128;
begin
if rising_edge(Clk1x) then
if aTestReset and c1DataValidOut = '0' then
tempQdata := 1;
tempIdata := 128;
elsif c1DataValidOut = '1' then
tempQdata := tempQdata+4;
tempIdata := tempIdata+4;
end if;
c1ExpectedData <= "0000000" & std_logic_vector(to_unsigned(tempQdata+3,17)) &
"0000000" & std_logic_vector(to_unsigned(tempIdata+3,17)) &
"0000000" & std_logic_vector(to_unsigned(tempQdata+2,17)) &
"0000000" & std_logic_vector(to_unsigned(tempIdata+2,17)) &
"0000000" & std_logic_vector(to_unsigned(tempQdata+1,17)) &
"0000000" & std_logic_vector(to_unsigned(tempIdata+1,17)) &
"0000000" & std_logic_vector(to_unsigned(tempQdata+0,17)) &
"0000000" & std_logic_vector(to_unsigned(tempIdata+0,17));
end if;
end process;
-- Process to continuously check output data from the DUT.
checker: process(Clk1x)
begin
if falling_edge(Clk1x) then
if c1DataValidOut = '1' then
assert c1DataOut = c1ExpectedData
report "ADC data out mismatch from expected"
severity error;
end if;
end if;
end process;
end RTL;
+206
View File
@@ -0,0 +1,206 @@
--
-- Copyright 2021 Ettus Research, a National Instruments Brand
--
-- SPDX-License-Identifier: LGPL-3.0-or-later
--
-- Module: tb_adc_gearbox_8x4
--
-- Description:
--
-- Self-checking testbench for adc_gearbox_8x4.
--
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity tb_adc_gearbox_8x4 is
end tb_adc_gearbox_8x4;
architecture RTL of tb_adc_gearbox_8x4 is
component adc_gearbox_8x4
port (
clk1x : in std_logic;
reset_n_1x : in std_logic;
adc_q_in_1x : in std_logic_vector(127 downto 0);
adc_i_in_1x : in std_logic_vector(127 downto 0);
valid_in_1x : in std_logic;
enable_1x : in std_logic;
clk2x : in std_logic;
swap_iq_2x : in std_logic;
adc_out_2x : out std_logic_vector(127 downto 0);
valid_out_2x : out std_logic);
end component;
signal cDataCheckNxtLo, cDataCheckLo: std_logic_vector(127 downto 0);
signal cDataCheckNxtHi : std_logic_vector(127 downto 0);
signal cDataCheckHi1, cDataCheckHi2: std_logic_vector(127 downto 0);
signal adc_i_in_1x : std_logic_vector(127 downto 0);
signal adc_out_2x : std_logic_vector(127 downto 0);
signal adc_q_in_1x : std_logic_vector(127 downto 0);
signal enable_1x : std_logic;
signal reset_n_1x : std_logic;
signal swap_iq_2x : std_logic;
signal valid_in_1x : std_logic;
signal valid_out_2x : std_logic;
signal StopSim : boolean;
constant kPer : time := 10 ns;
signal Clk : std_logic := '1';
signal Clk2x : std_logic := '1';
procedure ClkWait(X : positive := 1) is
begin
for i in 1 to X loop
wait until rising_edge(Clk);
end loop;
end procedure ClkWait;
begin
Clk <= not Clk after kPer/2 when not StopSim else '0';
Clk2x <= not Clk2x after kPer/4 when not StopSim else '0';
dut: adc_gearbox_8x4
port map (
clk1x => Clk,
reset_n_1x => reset_n_1x,
adc_q_in_1x => adc_q_in_1x,
adc_i_in_1x => adc_i_in_1x,
valid_in_1x => valid_in_1x,
enable_1x => enable_1x,
clk2x => Clk2x,
swap_iq_2x => swap_iq_2x,
adc_out_2x => adc_out_2x,
valid_out_2x => valid_out_2x
);
main: process
begin
swap_iq_2x <= '0';
valid_in_1x <= '0';
enable_1x <= '0';
reset_n_1x <= '0';
ClkWait(5);
reset_n_1x <= '1';
ClkWait(5);
-- Ensure the outputs are quiet.
ClkWait(20);
assert valid_out_2x'stable(kPer*20) and valid_out_2x = '0'
report "valid not stable at de-asserted at startup"
severity error;
assert adc_out_2x'stable(kPer*20) and (adc_out_2x = std_logic_vector(to_unsigned(0,128)))
report "data not stable at zero at startup"
severity error;
-- Valid asserted, Enable asserted, Enable de-asserted, Valid de-asserted.
ClkWait(10);
valid_in_1x <= '1';
ClkWait(10);
enable_1x <= '1';
ClkWait(110);
assert valid_out_2x'stable(kPer*100) and valid_out_2x = '1'
report "valid not stable at asserted"
severity error;
ClkWait(10);
enable_1x <= '0';
ClkWait(10);
valid_in_1x <= '0';
ClkWait(110);
assert valid_out_2x'stable(kPer*100) and valid_out_2x = '0'
report "valid not stable at de-asserted"
severity error;
-- Enable asserted, Valid asserted, Enable de-asserted, Valid de-asserted.
ClkWait(10);
enable_1x <= '1';
ClkWait(10);
valid_in_1x <= '1';
ClkWait(110);
assert valid_out_2x'stable(kPer*100) and valid_out_2x = '1'
report "valid not stable at asserted"
severity error;
ClkWait(10);
enable_1x <= '0';
ClkWait(10);
valid_in_1x <= '0';
ClkWait(110);
assert valid_out_2x'stable(kPer*100) and valid_out_2x = '0'
report "valid not stable at de-asserted"
severity error;
StopSim <= true;
wait;
end process;
-- Process to generate input data to DUT and expected output data.
driver: process(Clk)
variable tempQdata : integer := 1;
variable tempIdata : integer := 128;
variable qData8spc : std_logic_vector(127 downto 0);
variable iData8spc : std_logic_vector(127 downto 0);
begin
if rising_edge(Clk) then
qdata8Spc := std_logic_vector(to_unsigned(tempQdata+7,16)) & std_logic_vector(to_unsigned(tempQdata+6,16)) &
std_logic_vector(to_unsigned(tempQdata+5,16)) & std_logic_vector(to_unsigned(tempQdata+4,16)) &
std_logic_vector(to_unsigned(tempQdata+3,16)) & std_logic_vector(to_unsigned(tempQdata+2,16)) &
std_logic_vector(to_unsigned(tempQdata+1,16)) & std_logic_vector(to_unsigned(tempQdata ,16));
adc_q_in_1x <= qData8Spc;
iData8spc := std_logic_vector(to_unsigned(tempIdata+7,16)) & std_logic_vector(to_unsigned(tempIdata+6,16)) &
std_logic_vector(to_unsigned(tempIdata+5,16)) & std_logic_vector(to_unsigned(tempIdata+4,16)) &
std_logic_vector(to_unsigned(tempIdata+3,16)) & std_logic_vector(to_unsigned(tempIdata+2,16)) &
std_logic_vector(to_unsigned(tempIdata+1,16)) & std_logic_vector(to_unsigned(tempIdata ,16));
adc_i_in_1x <= iData8Spc;
cDataCheckNxtLo <= qData8spc( 63 downto 48) & iData8spc( 63 downto 48) &
qData8spc( 47 downto 32) & iData8spc( 47 downto 32) &
qData8spc( 31 downto 16) & iData8spc( 31 downto 16) &
qData8spc( 15 downto 0) & iData8spc( 15 downto 0);
cDataCheckNxtHi <= qData8spc(127 downto 112) & iData8spc(127 downto 112) &
qData8spc(111 downto 96) & iData8spc(111 downto 96) &
qData8spc( 95 downto 80) & iData8spc( 95 downto 80) &
qData8spc( 79 downto 64) & iData8spc( 79 downto 64);
tempQdata := tempQdata+8;
tempIdata := tempIdata+8;
end if;
end process;
-- Process to check DUT output with expected data.
checker: process(Clk2x)
variable tempout : integer := 1;
variable ExpectedData : std_logic_vector(127 downto 0) := (others => '0');
begin
if falling_edge(Clk2x) then
if Clk = '1' then
ExpectedData := cDataCheckLo;
else
ExpectedData := cDataCheckHi2;
end if;
if valid_out_2x = '1' then
assert adc_out_2x = ExpectedData
report "ADC data out mismatch from expected"
severity error;
tempout := tempout +1;
end if;
cDataCheckLo <= cDataCheckNxtLo;
cDataCheckHi1 <= cDataCheckNxtHi;
cDataCheckHi2 <= cDataCheckHi1;
end if;
end process;
end RTL;
+119
View File
@@ -0,0 +1,119 @@
--
-- Copyright 2021 Ettus Research, a National Instruments Brand
--
-- SPDX-License-Identifier: LGPL-3.0-or-later
--
-- Module: tb_capture_sysref
--
-- Description:
--
-- Self-checking testbench for tb_capture_sysref.
--
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity tb_capture_sysref is
end tb_capture_sysref;
architecture RTL of tb_capture_sysref is
component capture_sysref
port (
pll_ref_clk : in std_logic;
rfdc_clk : in std_logic;
sysref_in : in std_logic;
enable_rclk : in std_logic;
sysref_out_pclk : out std_logic;
sysref_out_rclk : out std_logic);
end component;
signal enable_rclk : std_logic := '0';
signal sysref_out_pclk : std_logic := '0';
signal sysref_out_rclk : std_logic := '0';
signal sysref_in : std_logic := '0';
signal SysrefDly, SysrefDlyDly, rSysref : std_logic := '0';
signal StopSim : boolean;
constant kPerPRC : time := 30 ns;
constant kPerRF : time := 10 ns;
signal PllRefClk : std_logic := '1';
signal RfdcClk : std_logic := '1';
procedure ClkWait(X : positive := 1) is
begin
for i in 1 to X loop
wait until rising_edge(PllRefClk);
end loop;
end procedure ClkWait;
begin
PllRefClk <= not PllRefClk after kPerPRC/2 when not StopSim else '0';
RfdcClk <= not RfdcClk after kPerRF/2 when not StopSim else '0';
dut: capture_sysref
port map (
pll_ref_clk => PllRefClk,
rfdc_clk => RfdcClk,
sysref_in => sysref_in,
enable_rclk => enable_rclk,
sysref_out_pclk => sysref_out_pclk,
sysref_out_rclk => sysref_out_rclk
);
main: process
begin
enable_rclk <= '1';
ClkWait(100);
wait until falling_edge(sysref_out_rclk);
ClkWait;
wait until falling_edge(RfdcClk);
enable_rclk <= '0';
ClkWait(100);
wait until falling_edge(RfdcClk);
enable_rclk <= '1';
ClkWait(100);
StopSim <= true;
wait;
end process;
sysref: process(PllRefClk)
variable count : integer := 1;
begin
if rising_edge(PllRefClk) then
count := count +1;
if count = 10 then
sysref_in <= not sysref_in;
count := 1;
end if;
end if;
end process;
checker_pll_ref_clk: process(PllRefClk)
begin
if falling_edge(PllRefClk) then
SysrefDly <= sysref_in;
SysrefDlyDly <= SysrefDly;
assert SysrefDlyDly = sysref_out_pclk
report "SYSREF incorrectly captured in the PllRefClk domain"
severity error;
end if;
end process;
checker_rfdc_clk: process(RfdcClk)
begin
if falling_edge(RfdcClk) then
rSysref <= sysref_out_pclk;
assert (rSysref = sysref_out_rclk) or (enable_rclk = '0')
report "SYSREF incorrectly captured in the RfdcClk domain."
severity error;
end if;
end process;
end RTL;
+197
View File
@@ -0,0 +1,197 @@
--
-- Copyright 2021 Ettus Research, a National Instruments Brand
--
-- SPDX-License-Identifier: LGPL-3.0-or-later
--
-- Module: tb_dac_gearbox_12x8
--
-- Description:
--
-- Self-checking testbench for a gearbox that decreases the SPCs from 12 to
-- 8.
--
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity tb_dac_gearbox_12x8 is
end tb_dac_gearbox_12x8;
architecture RTL of tb_dac_gearbox_12x8 is
signal TestStart : boolean;
signal ac1Reset_n : std_logic := '0';
signal arReset_n : std_logic := '0';
signal c1DataIn : std_logic_vector(383 downto 0) := (others => '0');
signal c1DataValidIn : std_logic := '0';
signal rDataOut : std_logic_vector(255 downto 0);
signal rReadyForOutput : std_logic := '1';
signal rDataValidOut : std_logic;
signal rDataToCheck, rDataToCheckDly0, rDataToCheckDly1, rDataToCheckDly2,
rDataToCheckDly3, rDataToCheckDly4
: std_logic_vector(255 downto 0) := (others => '0');
signal StopSim : boolean;
constant kPer : time := 12 ns;
signal Clk1x: std_logic := '1';
signal RfClk: std_logic := '1';
procedure RfClkWait(X : positive := 1) is
begin
for i in 1 to X loop
wait until rising_edge(RfClk);
end loop;
end procedure RfClkWait;
procedure Clk1xWait(X : positive := 1) is
begin
for i in 1 to X loop
wait until rising_edge(Clk1x);
end loop;
end procedure Clk1xWait;
begin
Clk1x <= not Clk1x after kPer/4 when not StopSim else '0';
RfClk <= not RfClk after kPer/6 when not StopSim else '0';
dut: entity WORK.dac_gearbox_12x8 (RTL)
port map (
Clk1x => Clk1x,
RfClk => RfClk,
ac1Reset_n => ac1Reset_n,
arReset_n => arReset_n,
c1DataIn => c1DataIn,
c1DataValidIn => c1DataValidIn,
rDataOut => rDataOut,
rReadyForOutput => rReadyForOutput,
rDataValidOut => rDataValidOut
);
main: process
-- Procedure to start and stop data generation.
-- WaitCycles : This is a wait in Clk1x cycle. This is used to shift data
-- valid assertion. Depending on the Clk1x cycle, data valid
-- will be asserted either when both RfClk and Clk1x are phase
-- aligned or when both clocks are not phase aligned.
procedure PhaseTest(WaitCycles : positive := 1) is
begin
for i in 0 to 31 loop
-- Wait for certain RfClk cycles before starting the test.
Clk1xWait(WaitCycles);
TestStart <= true;
-- Random wait
Clk1xWait(1000+i);
TestStart <= false;
-- wait for few clock cycles for the output data valid to de-assert.
Clk1xWait(10);
end loop;
end procedure;
begin
ac1Reset_n <= '0';
arReset_n <= '0';
TestStart <= false;
Clk1xWait(5);
ac1Reset_n <= '1';
arReset_n <= '1';
rReadyForOutput <= '1';
-- RfClk and Clk1x are phase aligned
PhaseTest(1);
-- RfClk and Clk1x are phase aligned
PhaseTest(2);
-- RfClk and Clk1x are not phase aligned
PhaseTest(3);
-- Stop data input to the DUT and wait for few clock cycles for the output
-- data valid to be de-asserted.
TestStart <= false;
RfClkWait(10);
StopSim <= true;
wait;
end process;
-- Process to generate input data.
driver: process(Clk1x)
variable qDataIn : unsigned(15 downto 0) := x"0001";
variable iDataIn : unsigned(15 downto 0) := x"0080";
begin
if rising_edge(Clk1x) then
c1DataValidIn <= '0';
if TestStart then
c1DataValidIn <= '1';
c1DataIn <= std_logic_vector((qDataIn+11) & (iDataIn+11) &
(qDataIn+10) & (iDataIn+10) &
(qDataIn+9) & (iDataIn+9) &
(qDataIn+8) & (iDataIn+8) &
(qDataIn+7) & (iDataIn+7) &
(qDataIn+6) & (iDataIn+6) &
(qDataIn+5) & (iDataIn+5) &
(qDataIn+4) & (iDataIn+4) &
(qDataIn+3) & (iDataIn+3) &
(qDataIn+2) & (iDataIn+2) &
(qDataIn+1) & (iDataIn+1) &
(qDataIn+0) & (iDataIn+0));
qDataIn := qDataIn+12;
iDataIn := iDataIn+12;
else
c1DataValidIn <= '0';
qDataIn := x"0001";
iDataIn := x"0080";
end if;
end if;
end process;
-- Process to generate expected output data.
ExpectedData: process(RfClk)
variable qDataOut : unsigned(15 downto 0) := x"0001";
variable iDataOut : unsigned(15 downto 0) := x"0080";
begin
if rising_edge(RfClk) then
if TestStart then
rDataToCheck <= std_logic_vector((qDataOut+7) & (iDataOut+7) &
(qDataOut+6) & (iDataOut+6) &
(qDataOut+5) & (iDataOut+5) &
(qDataOut+4) & (iDataOut+4) &
(qDataOut+3) & (iDataOut+3) &
(qDataOut+2) & (iDataOut+2) &
(qDataOut+1) & (iDataOut+1) &
(qDataOut+0) & (iDataOut+0));
-- Data output that has to be verified.
qDataOut := qDataOut+8;
iDataOut := iDataOut+8;
else
qDataOut := x"0001";
iDataOut := x"0080";
end if;
rDataToCheckDly0 <= rDataToCheck;
rDataToCheckDly1 <= rDataToCheckDly0;
rDataToCheckDly2 <= rDataToCheckDly1;
rDataToCheckDly3 <= rDataToCheckDly2;
rDataToCheckDly4 <= rDataToCheckDly3;
end if;
end process;
-- Process to check output data with expected data.
checker: process(RfClk)
begin
if falling_edge(RfClk) then
if rDataValidOut = '1' then
assert rDataOut = rDataToCheckDly4
report "DAC data out mismatch from expected"
severity error;
end if;
end if;
end process;
end RTL;
+168
View File
@@ -0,0 +1,168 @@
--
-- Copyright 2021 Ettus Research, a National Instruments Brand
--
-- SPDX-License-Identifier: LGPL-3.0-or-later
--
-- Module: tb_dac_gearbox_4x2
--
-- Description:
--
-- Self-checking testbench used to test the gearbox that reduces a 4 SPC data
-- into a 2 SPC data.
--
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity tb_dac_gearbox_4x2 is
end tb_dac_gearbox_4x2;
architecture RTL of tb_dac_gearbox_4x2 is
component dac_gearbox_4x2
port (
clk1x : in std_logic;
reset_n_1x : in std_logic;
data_in_1x : in std_logic_vector(127 downto 0);
valid_in_1x : in std_logic;
ready_out_1x : out std_logic;
clk2x : in std_logic;
data_out_2x : out std_logic_vector(63 downto 0);
valid_out_2x : out std_logic);
end component;
signal TestStart : boolean;
signal data_in_1x : std_logic_vector(127 downto 0);
signal data_out_2x : std_logic_vector(63 downto 0);
signal ready_out_1x : std_logic;
signal reset_n_1x : std_logic;
signal valid_in_1x : std_logic;
signal valid_out_2x : std_logic;
signal StopSim : boolean;
constant kPer : time := 10 ns;
signal Clk: std_logic := '1';
signal Clk2x: std_logic := '1';
signal c2DataToCheck, c2DataToCheckDly0, c2DataToCheckDly1, c2DataToCheckDly2
: std_logic_vector(63 downto 0) := (others => '0');
procedure ClkWait(X : positive := 1) is
begin
for i in 1 to X loop
wait until rising_edge(Clk);
end loop;
end procedure ClkWait;
begin
Clk <= not Clk after kPer/2 when not StopSim else '0';
Clk2x <= not Clk2x after kPer/4 when not StopSim else '0';
dut: dac_gearbox_4x2
port map (
clk1x => Clk,
reset_n_1x => reset_n_1x,
data_in_1x => data_in_1x,
valid_in_1x => valid_in_1x,
ready_out_1x => ready_out_1x,
clk2x => Clk2x,
data_out_2x => data_out_2x,
valid_out_2x => valid_out_2x
);
main: process
begin
reset_n_1x <= '0';
TestStart <= false;
ClkWait(5);
reset_n_1x <= '1';
ClkWait(5);
-- Ensure the outputs are quiet.
ClkWait(20);
assert valid_out_2x'stable(kPer*20) and valid_out_2x = '0'
report "valid not stable at de-asserted at startup"
severity error;
assert data_out_2x'stable(kPer*20) and (data_out_2x = x"0000000000000000")
report "data not stable at zero at startup"
severity error;
-- Valid asserted, Enable asserted, Enable de-asserted, Valid de-asserted.
ClkWait(10);
TestStart <= true;
ClkWait(110);
assert valid_out_2x'stable(kPer*100) and valid_out_2x = '1'
report "valid not stable at asserted"
severity error;
TestStart <= false;
ClkWait(10);
StopSim <= true;
wait;
end process;
-- Process to generate input data to DUT.
driver: process(Clk)
variable tempQdata : integer := 1;
variable tempIdata : integer := 128;
begin
if rising_edge(Clk) then
valid_in_1x <= '0';
if TestStart then
valid_in_1x <= '1';
data_in_1x <= std_logic_vector(to_unsigned(tempQdata+3,16)) & std_logic_vector(to_unsigned(tempIdata+3,16)) &
std_logic_vector(to_unsigned(tempQdata+2,16)) & std_logic_vector(to_unsigned(tempIdata+2,16)) &
std_logic_vector(to_unsigned(tempQdata+1,16)) & std_logic_vector(to_unsigned(tempIdata+1,16)) &
std_logic_vector(to_unsigned(tempQdata+0,16)) & std_logic_vector(to_unsigned(tempIdata+0,16));
tempQdata := tempQdata+4;
tempIdata := tempIdata+4;
end if;
end if;
end process;
-- Process to generate expected data out of the DUT.
ExpectedData: process(Clk2x)
variable qDataOut : unsigned(15 downto 0) := x"0001";
variable iDataOut : unsigned(15 downto 0) := x"0080";
begin
if rising_edge(Clk2x) then
if TestStart then
c2DataToCheck <= std_logic_vector((qDataOut+1) & (iDataOut+1) &
(qDataOut+0) & (iDataOut+0));
qDataOut := qDataOut+2;
iDataOut := iDataOut+2;
else
qDataOut := x"0001";
iDataOut := x"0080";
end if;
c2DataToCheckDly0 <= c2DataToCheck;
c2DataToCheckDly1 <= c2DataToCheckDly0;
c2DataToCheckDly2 <= c2DataToCheckDly1;
end if;
end process;
-- Process to check DUT output data with expected data.
checker: process(Clk2x)
begin
if falling_edge(Clk2x) then
if valid_out_2x = '1' then
assert data_out_2x = c2DataToCheckDly2
report "DAC data out mismatch from expected"
severity error;
end if;
assert ready_out_1x = '1'
report "Ready for output is not asserted"
severity error;
end if;
end process;
end RTL;
+187
View File
@@ -0,0 +1,187 @@
--
-- Copyright 2021 Ettus Research, a National Instruments Brand
--
-- SPDX-License-Identifier: LGPL-3.0-or-later
--
-- Module: tb_dac_gearbox_6x12
--
-- Description:
--
-- Self-checking testbench used to test the gearbox that expands a 6 SPC data
-- into a 12 SPC data.
--
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity tb_dac_gearbox_6x12 is
end tb_dac_gearbox_6x12;
architecture RTL of tb_dac_gearbox_6x12 is
signal TestStart : boolean;
signal ac1Reset_n : std_logic;
signal ac2Reset_n : std_logic;
signal c1DataOut : std_logic_vector(383 downto 0);
signal c1DataValidOut : std_logic;
signal c2DataIn : std_logic_vector(191 downto 0) := (others => '0');
signal c2DataValidIn : std_logic := '0';
signal InPhase : boolean := false;
signal c1DataToCheck, c1DataToCheckDly0, c1DataToCheckDly1, c1DataToCheckDly2
: std_logic_vector(383 downto 0) := (others => '0');
signal StopSim : boolean;
constant kPer : time := 12 ns;
signal Clk1x: std_logic := '1';
signal Clk2x: std_logic := '1';
procedure Clk2xWait(X : positive := 1) is
begin
for i in 1 to X loop
wait until rising_edge(Clk2x);
end loop;
end procedure Clk2xWait;
begin
Clk1x <= not Clk1x after kPer/4 when not StopSim else '0';
Clk2x <= not Clk2x after kPer/8 when not StopSim else '0';
dut: entity WORK.dac_gearbox_6x12 (RTL)
port map (
Clk1x => Clk1x,
Clk2x => Clk2x,
ac1Reset_n => ac1Reset_n,
ac2Reset_n => ac2Reset_n,
c2DataIn => c2DataIn,
c2DataValidIn => c2DataValidIn,
c1DataOut => c1DataOut,
c1DataValidOut => c1DataValidOut
);
main: process
-- Procedure to start and stop data generation.
-- WaitCycles : This is a wait in Clk2x cycle. This is used to shift data
-- valid assertion. Depending on the Clk2x cycle, data valid
-- will be asserted either when both Clk1x and Clk2x are phase
-- aligned or when both clocks are not phase aligned.
-- Phase : This input is used in the logic that is used to check
-- output data with expected data. If data valid was asserted
-- when both clocks were phase aligned, then this input is
-- set to true and vice versa.
procedure PhaseTest(WaitCycles : positive := 1;
Phase : boolean := false) is
begin
-- Wait for certain Clk2x cycles before starting the test.
Clk2xWait(WaitCycles);
InPhase <= Phase;
TestStart <= true;
Clk2xWait(1000); -- Random wait.
TestStart <= false;
-- wait for few clock cycles for the output data valid to de-assert.
Clk2xWait(10);
end procedure;
begin
-- Assert and de-assert reset.
ac1Reset_n <= '0';
ac2Reset_n <= '0';
TestStart <= false;
Clk2xWait(5);
ac1Reset_n <= '1';
ac2Reset_n <= '1';
PhaseTest(1, true);
PhaseTest(3, false);
PhaseTest(5, true);
-- Stop data input to the DUT and wait for few clock cycles for the output
-- data valid to be de-asserted.
TestStart <= false;
Clk2xWait(10);
StopSim <= true;
wait;
end process;
driver: process(Clk2x)
variable tempQdata : unsigned(15 downto 0) := x"0001";
variable tempIdata : unsigned(15 downto 0) := x"0080";
begin
if rising_edge(Clk2x) then
c2DataValidIn <= '0';
if TestStart then
c2DataValidIn <= '1';
c2DataIn <= std_logic_vector((tempQdata+5) & (tempIdata+5) &
(tempQdata+4) & (tempIdata+4) &
(tempQdata+3) & (tempIdata+3) &
(tempQdata+2) & (tempIdata+2) &
(tempQdata+1) & (tempIdata+1) &
(tempQdata+0) & (tempIdata+0));
tempQdata := tempQdata +6;
tempIdata := tempIdata +6;
else
c2DataValidIn <= '0';
tempQdata := x"0001";
tempIdata := x"0080";
end if;
end if;
end process;
-- Process to generate expected data out of the DUT.
ExpectedData: process(Clk1x)
variable qDataOut : unsigned(15 downto 0) := x"0001";
variable iDataOut : unsigned(15 downto 0) := x"0080";
begin
if rising_edge(Clk1x) then
if TestStart then
c1DataToCheck <= std_logic_vector((qDataOut+11) & (iDataOut+11) &
(qDataOut+10) & (iDataOut+10) &
(qDataOut+9) & (iDataOut+9) &
(qDataOut+8) & (iDataOut+8) &
(qDataOut+7) & (iDataOut+7) &
(qDataOut+6) & (iDataOut+6) &
(qDataOut+5) & (iDataOut+5) &
(qDataOut+4) & (iDataOut+4) &
(qDataOut+3) & (iDataOut+3) &
(qDataOut+2) & (iDataOut+2) &
(qDataOut+1) & (iDataOut+1) &
(qDataOut+0) & (iDataOut+0));
qDataOut := qDataOut+12;
iDataOut := iDataOut+12;
else
qDataOut := x"0001";
iDataOut := x"0080";
end if;
c1DataToCheckDly0 <= c1DataToCheck;
c1DataToCheckDly1 <= c1DataToCheckDly0;
c1DataToCheckDly2 <= c1DataToCheckDly1;
end if;
end process;
-- Process to check output data with expected data.
checker: process(Clk1x)
begin
if falling_edge(Clk1x) then
if c1DataValidOut = '1' and InPhase then
assert c1DataOut = c1DataToCheckDly1
report "ADC data out mismatch from expected"
severity warning;
elsif c1DataValidOut = '1' and (not InPhase) then
assert c1DataOut = c1DataToCheckDly2
report "ADC data out mismatch from expected"
severity warning;
end if;
end if;
end process;
end RTL;
+125
View File
@@ -0,0 +1,125 @@
--
-- Copyright 2021 Ettus Research, a National Instruments Brand
--
-- SPDX-License-Identifier: LGPL-3.0-or-later
--
-- Module: tb_ddc_400m_saturate
--
-- Description:
--
-- Self-checking testbench used to check the saturation logic needed in DDC.
--
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
library WORK;
use WORK.PkgRf.all;
entity tb_ddc_400m_saturate is
end tb_ddc_400m_saturate;
architecture RTL of tb_ddc_400m_saturate is
component ddc_400m_saturate
port (
Clk : in std_logic;
cDataIn : in std_logic_vector(191 downto 0);
cDataValidIn : in std_logic;
cDataOut : out std_logic_vector(127 downto 0);
cDataValidOut : out std_logic);
end component;
signal TestStart : boolean := false;
signal cDataIn : std_logic_vector(191 downto 0);
signal cDataOut : std_logic_vector(127 downto 0);
signal cDataValidIn : std_logic;
signal cDataValidOut : std_logic;
signal StopSim : boolean;
constant kPer : time := 10 ns;
constant kSamplesPerClock : integer := 8;
signal Clk: std_logic := '1';
procedure ClkWait(X : positive := 1) is
begin
for i in 1 to X loop
wait until rising_edge(Clk);
end loop;
end procedure ClkWait;
begin
Clk <= not Clk after kPer/2 when not StopSim else '0';
dut: ddc_400m_saturate
port map (
Clk => Clk,
cDataIn => cDataIn,
cDataValidIn => cDataValidIn,
cDataOut => cDataOut,
cDataValidOut => cDataValidOut);
main: process
begin
ClkWait;
TestStart <= false;
ClkWait;
TestStart <= true;
-- This wait is needed to sweep through the entire range of 17 bits signed
-- value. Since we operate the saturation logic with 8 samples per cycle,
-- we need to wait for 2^kDdcDataOutWidth/8. We are adding an extra 10
-- clock cycles wait just as a buffer for the DUT latency.
ClkWait(2**kDdcDataOutWidth/kSamplesPerClock + 10);
StopSim <= true;
wait;
end process;
-- Process to generate 17-bit signed data.
DataGen: process(Clk)
variable Sample : Sample17_t := kSmallest17;
begin
if falling_edge(Clk) then
if TestStart then
cDataValidIn <= '1';
cDataIn <= "0000000" & std_logic_vector(Sample+kSamplesPerClock-1) &
"0000000" & std_logic_vector(Sample+kSamplesPerClock-2) &
"0000000" & std_logic_vector(Sample+kSamplesPerClock-3) &
"0000000" & std_logic_vector(Sample+kSamplesPerClock-4) &
"0000000" & std_logic_vector(Sample+kSamplesPerClock-5) &
"0000000" & std_logic_vector(Sample+kSamplesPerClock-6) &
"0000000" & std_logic_vector(Sample+kSamplesPerClock-7) &
"0000000" & std_logic_vector(Sample+kSamplesPerClock-8);
Sample := Sample +8;
end if;
end if;
end process;
-- Check if saturation and data packing is done correctly.
DataCheck: process(Clk)
variable Sample : Sample17_t := kSmallest17;
variable ExpectedData : std_logic_vector(15 downto 0);
begin
if falling_edge(Clk) then
if cDataValidOut then
for i in 1 to 8 loop
ExpectedData := tb_saturate(std_logic_vector(Sample));
assert cDataOut(kSatDataWidth*i-1 downto kSatDataWidth*(i-1)) = ExpectedData
report "Saturation data out mismatch in index : " & to_string(i) & LF &
"Expected data is : " & to_hstring(ExpectedData) & LF &
"Received data is : " & to_hstring(cDataOut(kSatDataWidth*i-1 downto kSatDataWidth*(i-1)))
severity error;
Sample := Sample+1;
end loop;
end if;
end if;
end process;
end RTL;
+133
View File
@@ -0,0 +1,133 @@
--
-- Copyright 2021 Ettus Research, a National Instruments Brand
--
-- SPDX-License-Identifier: LGPL-3.0-or-later
--
-- Module: tb_duc_400m_saturate
--
-- Description:
--
-- Self-checking testbench used to check the saturation logic needed in DDC.
--
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
library WORK;
use WORK.PkgRf.all;
entity tb_duc_400m_saturate is
end tb_duc_400m_saturate;
architecture RTL of tb_duc_400m_saturate is
component duc_400m_saturate
port (
Clk : in std_logic;
cDataIn : in std_logic_vector(287 downto 0);
cDataValidIn : in std_logic;
cReadyForInput : out std_logic;
cDataOut : out std_logic_vector(191 downto 0);
cDataValidOut : out std_logic := '0');
end component;
signal TestStart : boolean := false;
signal cDataIn : std_logic_vector(287 downto 0);
signal cDataOut : std_logic_vector(191 downto 0);
signal cDataValidIn : std_logic;
signal cDataValidOut : std_logic;
signal StopSim : boolean;
constant kPer : time := 10 ns;
constant kSamplesPerClock : integer := 12;
signal Clk: std_logic := '1';
procedure ClkWait(X : positive := 1) is
begin
for i in 1 to X loop
wait until rising_edge(Clk);
end loop;
end procedure ClkWait;
begin
Clk <= not Clk after kPer/2 when not StopSim else '0';
-- cReadyForInput is a constant in the design and is not being tested.
dut: duc_400m_saturate
port map (
Clk => Clk,
cDataIn => cDataIn,
cDataValidIn => cDataValidIn,
cReadyForInput => open,
cDataOut => cDataOut,
cDataValidOut => cDataValidOut);
main: process
begin
ClkWait;
TestStart <= false;
ClkWait;
TestStart <= true;
-- This wait is needed to sweep through the entire range of 18 bits signed
-- value. Since we operate the saturation logic with 12 samples per cycle,
-- we need to wait for 2^kDucDataOutWidth/12. We are adding an extra 10
-- clock cycles wait just as a buffer for the DUT latency.
ClkWait(2**kDucDataOutWidth/kSamplesPerClock + 10);
StopSim <= true;
wait;
end process;
-- Process to generate 18-bit signed data.
DataGen: process(Clk)
variable Sample : Sample18_t := kSmallest18;
begin
if falling_edge(Clk) then
if TestStart then
cDataValidIn <= '1';
cDataIn <= "000000" & std_logic_vector(Sample+kSamplesPerClock-1) &
"000000" & std_logic_vector(Sample+kSamplesPerClock-2) &
"000000" & std_logic_vector(Sample+kSamplesPerClock-3) &
"000000" & std_logic_vector(Sample+kSamplesPerClock-4) &
"000000" & std_logic_vector(Sample+kSamplesPerClock-5) &
"000000" & std_logic_vector(Sample+kSamplesPerClock-6) &
"000000" & std_logic_vector(Sample+kSamplesPerClock-7) &
"000000" & std_logic_vector(Sample+kSamplesPerClock-8) &
"000000" & std_logic_vector(Sample+kSamplesPerClock-9) &
"000000" & std_logic_vector(Sample+kSamplesPerClock-10) &
"000000" & std_logic_vector(Sample+kSamplesPerClock-11) &
"000000" & std_logic_vector(Sample+kSamplesPerClock-12);
Sample := Sample +12;
end if;
end if;
end process;
-- Check if saturation and data packing is done correctly.
DataCheck: process(Clk)
variable Sample : Sample18_t := kSmallest18;
variable ExpectedData : std_logic_vector(15 downto 0);
begin
if falling_edge(Clk) then
if cDataValidOut then
for i in 1 to 12 loop
ExpectedData := tb_saturate(std_logic_vector(Sample));
assert cDataOut(kSatDataWidth*i-1 downto kSatDataWidth*(i-1)) = ExpectedData
report "Saturation data out mismatch in index : " & to_string(i) & LF &
"Expected data is : " & to_hstring(ExpectedData) & LF &
"Received data is : " & to_hstring(cDataOut(kSatDataWidth*i-1 downto kSatDataWidth*(i-1)))
severity error;
Sample := Sample+1;
end loop;
end if;
end if;
end process;
end RTL;
+281
View File
@@ -0,0 +1,281 @@
--
-- Copyright 2021 Ettus Research, a National Instruments Brand
--
-- SPDX-License-Identifier: LGPL-3.0-or-later
--
-- Module: tb_rf_nco_reset
--
-- Description:
--
-- Self-checking testbench for NCO reset sequencing.
--
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity tb_rf_nco_reset is
end tb_rf_nco_reset;
architecture RTL of tb_rf_nco_reset is
signal cAdc0xNcoUpdateReq : std_logic;
signal cAdc2xNcoUpdateReq : std_logic;
signal cDac0xNcoUpdateReq : std_logic;
signal cDac0xSysrefIntGating : std_logic;
signal cDac0xSysrefIntReenable : std_logic;
signal cDac1xNcoUpdateReq : std_logic;
signal cNcoPhaseRst : std_logic;
signal cNcoUpdateEn : std_logic_vector(5 downto 0);
signal dNcoResetDone : std_logic;
signal cDac0xNcoUpdateBusy : std_logic_vector(1 downto 0) := "00";
signal dStartNcoReset : std_logic := '0';
signal cAdc0xNcoUpdateBusy : std_logic := '0';
signal cAdc2xNcoUpdateBusy : std_logic := '0';
signal cDac1xNcoUpdateBusy : std_logic := '0';
signal cSysref_ms, cSysref : std_logic := '0';
signal cSysrefDlyd : std_logic_vector(1 downto 0) := "00";
signal cDac0xSysrefIntGatingDlyd : std_logic := '0';
signal cNcoPhaseRstDlyd : std_logic_vector(2 downto 0) := "000";
signal cWrCount : integer := 0;
type RfdcNcoState_t is (Idle, GateSysref, UpdateReq, CheckUpdate,
SysrefEn, WaitForSysref, ResetDone);
signal cRfdcNcoState : RfdcNcoState_t := Idle;
signal StopSim : boolean;
constant kConfigClkPer : time := 25 ns;
-- SYSREF period is 2.5 MHz.
constant kSysrefPer : time := 400 ns;
-- DataClk period is 125 MHz and generated from the same clocking chip that
-- generated SYSREF and are related.
constant kDataClkPer : time := kSysrefPer/50;
signal ConfigClk : std_logic := '0';
signal DataClk : std_logic := '0';
signal dSysref : std_logic := '0';
procedure DataClkWait(X : positive := 1) is
begin
for i in 1 to X loop
wait until rising_edge(DataClk);
end loop;
end procedure DataClkWait;
procedure ConfigClkWait(X : positive := 1) is
begin
for i in 1 to X loop
wait until rising_edge(ConfigClk);
end loop;
end procedure ConfigClkWait;
procedure SysrefWait(X : positive := 1) is
begin
for i in 1 to X loop
wait until rising_edge(dSysref);
end loop;
end procedure SysrefWait;
begin
ConfigClk <= not ConfigClk after kConfigClkPer/2 when not StopSim else '0';
DataClk <= not DataClk after kDataClkPer/2 when not StopSim else '0';
dSysref <= not dSysref after kSysrefPer/2 when not StopSim else '0';
-- Both cNcoPhaseRst and cNcoUpdateEn are constants in the DUT.
dut: entity WORK.rf_nco_reset (RTL)
port map (
ConfigClk => ConfigClk,
DataClk => DataClk,
dSysref => dSysref,
dStartNcoReset => dStartNcoReset,
cDac0xNcoUpdateBusy => cDac0xNcoUpdateBusy,
cDac0xNcoUpdateReq => cDac0xNcoUpdateReq,
cDac0xSysrefIntGating => cDac0xSysrefIntGating,
cDac0xSysrefIntReenable => cDac0xSysrefIntReenable,
cDac1xNcoUpdateBusy => cDac1xNcoUpdateBusy,
cDac1xNcoUpdateReq => cDac1xNcoUpdateReq,
cAdc0xNcoUpdateBusy => cAdc0xNcoUpdateBusy,
cAdc0xNcoUpdateReq => cAdc0xNcoUpdateReq,
cAdc2xNcoUpdateBusy => cAdc2xNcoUpdateBusy,
cAdc2xNcoUpdateReq => cAdc2xNcoUpdateReq,
cNcoPhaseRst => cNcoPhaseRst,
cNcoUpdateEn => cNcoUpdateEn,
dNcoResetDone => dNcoResetDone
);
main: process
-- Procedure to sweep the entire SYSREF period.
-- When we strobe dStartNcoReset for one DataClk cycle. NCO reset sequence
-- is initiated. In this procedure, we sweep the dStartNcoReset strobe the
-- entire SYSREF cycle.
procedure SysrefSweep is
constant kSysrefInRfCycles : integer := kSysrefPer/kDataClkPer;
begin
for i in 1 to kSysrefInRfCycles loop
wait until cDac0xSysrefIntGating = '0' for 1 us;
assert cDac0xSysrefIntGating = '0'
report "NCO phase reset does not de-assert"
severity error;
SysrefWait;
DataClkWait(i);
dStartNcoReset <= '0';
DataClkWait;
dStartNcoReset <= '1';
DataClkWait;
dStartNcoReset <= '0';
-- Wait for a minimum of 3 SYSREF period. 1 SYSREF edge is used to
-- initiate NCO reset, 1 SYSREF edge is used to re-enable SYSREF and 1
-- SYSREF edge is used by RFDC to reset all NCOs.
SysrefWait(3);
end loop;
end procedure;
begin
-- Strobe dStartNcoReset across entire SYSREF period.
SysrefSweep;
-- Wait for a minimum of 3 SYSREF cycles to make sure NCO reset is complete.
SysrefWait(3);
StopSim <= true;
wait;
end process;
-- Process to mimic RFDC NCO reset
-- This state machine is based of "NCO frequency hopping" section in PG269
-- (v2.2). Refer to multi-mode subsection for more details.
MimicRfdc: process(ConfigClk)
begin
if falling_edge(ConfigClk) then
cRfdcNcoState <= Idle;
case cRfdcNcoState is
-- Wait until SYSREF internal gating is asserted.
when Idle =>
cWrCount <= 0;
if cDac0xSysrefIntGating = '1' then
cRfdcNcoState <= GateSysref;
end if;
-- Change cDac0xNcoUpdateBusy to "11" to indicate SYSREF is gated
-- internally when NCO update is requested on DAC tile 228.
-- cDac0xNcoUpdateBusy(0) is set to '1', the SYSREF is gated and
-- cDac0xNcoUpdateBusy(1) is set to '1', to indicate the NCO reset
-- process has started, but not complete.
when GateSysref =>
cRfdcNcoState <= GateSysref;
if cDac0xNcoUpdateReq = '1' then
cRfdcNcoState <= UpdateReq;
cDac0xNcoUpdateBusy <= "11";
end if;
-- If NCO reset is requested on other tiles, assert NCO update busy on
-- other tiles as well.
when UpdateReq =>
cRfdcNcoState <= CheckUpdate;
cDac1xNcoUpdateBusy <= cDac1xNcoUpdateReq;
cAdc0xNcoUpdateBusy <= cAdc0xNcoUpdateReq;
cAdc2xNcoUpdateBusy <= cAdc2xNcoUpdateReq;
-- It takes 5 clock cycles to update each RFDC internal registers with
-- the used request change. In rf_nco_reset entity, we only want to
-- reset the NCO, which is a single bit. So, it should take only 5
-- ConfigClk for the update. When the internal register is updated, set
-- cDac0xNcoUpdateBusy(0) to '0'.
when CheckUpdate =>
cRfdcNcoState <= CheckUpdate;
if cWrCount > 4 then
cRfdcNcoState <= SysrefEn;
cDac0xNcoUpdateBusy <= "10"; --Indicates that SYSREF is gated.
cDac1xNcoUpdateBusy <= '0';
cAdc0xNcoUpdateBusy <= '0';
cAdc2xNcoUpdateBusy <= '0';
end if;
cWrCount <= cWrCount + 1;
-- Wait until internal SYSREF gating is disabled.
when SysrefEn =>
cWrCount <= 0;
cRfdcNcoState <= SysrefEn;
if cDac0xSysrefIntReenable = '1' then
if cSysrefDlyd(0) = '0' and cSysref = '1' then
cDac0xNcoUpdateBusy <= "00"; --Indicates that NCO reset is complete.
cRfdcNcoState <= ResetDone;
else
cRfdcNcoState <= WaitForSysref;
end if;
end if;
-- NCO reset is done on the rising edge of SYSREF. When NCO reset is
-- complete, set cDac0xNcoUpdateBusy(1) to '0'.
when WaitForSysref =>
cRfdcNcoState <= WaitForSysref;
if cSysrefDlyd(0) = '0' and cSysref = '1' then
cDac0xNcoUpdateBusy <= "00"; --Indicates that NCO reset is complete.
cRfdcNcoState <= ResetDone;
end if;
-- Wait in this state, until the next NCO reset is requested.
when ResetDone =>
cRfdcNcoState <= ResetDone;
if cDac0xSysrefIntGating = '1' then
cRfdcNcoState <= GateSysref;
end if;
end case;
end if;
end process;
-- SYSREF clock crossing from DataClk to ConfigClk and some pipelines.
ConfigClkSysref: process(ConfigClk)
begin
if rising_edge(ConfigClk) then
cSysref_ms <= dSysref;
cSysref <= cSysref_ms;
cSysrefDlyd <= cSysrefDlyd(cSysrefDlyd'high-1) & cSysref;
cDac0xSysrefIntGatingDlyd <= cDac0xSysrefIntGating;
cNcoPhaseRstDlyd <= cNcoPhaseRstDlyd(cNcoPhaseRstDlyd'high downto 1)
& cDac0xNcoUpdateBusy(1);
end if;
end process;
-- Assertions
process(ConfigClk)
begin
if falling_edge(ConfigClk) then
--Check if cNcoPhaseRst is a constant of '1'.
assert cNcoPhaseRst = '1'
report "NCO phase reset signal should be constant."
severity error;
-- Check if cNcoUpdateEn is a constant of "100000".
assert cNcoUpdateEn = "100000"
report "NCO phase reset signal should be constant."
severity error;
-- Check if NCO reset was requested on the rising edge of SYSREF.
if cDac0xSysrefIntGating = '1' and cDac0xSysrefIntGatingDlyd = '0' then
assert cSysrefDlyd = "01"
report "NCO reset did not start on SYSREF rising edge"
severity error;
end if;
-- We wait for couple of clock cycles after NCO done signal is toggled in
-- from the RFDC. RFDC uses cDac0xNcoUpdateBusy(1) to indicate NCO reset
-- process is done. It is important to wait a minimum of three clock
-- cycles before this check is done. This wait is needed for clock
-- crossing.
if cNcoPhaseRstDlyd(2) = '1' and cNcoPhaseRstDlyd(1) = '0' then
assert dNcoResetDone = '1'
report "NCO Reset done should have been asserted after NCO " &
"reset request is de-asserted"
severity error;
end if;
end if;
end process;
end RTL;
+436
View File
@@ -0,0 +1,436 @@
--
-- Copyright 2021 Ettus Research, a National Instruments Brand
--
-- SPDX-License-Identifier: LGPL-3.0-or-later
--
-- Module: tb_rf_reset_controller
--
-- Description:
--
-- Testbench for rf_reset_controller.
--
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
library WORK;
use WORK.PkgRFDC_REGS_REGMAP.all;
entity tb_rf_reset_controller is
end tb_rf_reset_controller;
architecture RTL of tb_rf_reset_controller is
component rf_reset_controller
port (
ConfigClk : in std_logic;
DataClk : in std_logic;
PllRefClk : in std_logic;
RfClk : in std_logic;
RfClk2x : in std_logic;
DataClk2x : in std_logic;
dAdcResetPulse : in std_logic;
dDacResetPulse : in std_logic;
dAdcDataOutReset_n : out std_logic;
r2AdcFirReset_n : out std_logic;
rAdcRfdcAxiReset_n : out std_logic;
rAdcEnableData : out std_logic;
rAdcGearboxReset_n : out std_logic;
dDacDataInReset_n : out std_logic;
r2DacFirReset_n : out std_logic;
d2DacFirReset_n : out std_logic;
rDacRfdcAxiReset_n : out std_logic;
rDacGearboxReset_n : out std_logic;
cSoftwareControl : in std_logic_vector(31 downto 0);
cSoftwareStatus : out std_logic_vector(31 downto 0));
end component;
signal cSoftwareStatus : std_logic_vector(31 downto 0);
signal r2AdcFirReset_n : std_logic;
signal r2DacFirReset_n : std_logic;
signal rAdcGearboxReset_n : std_logic;
signal rDacGearboxReset_n : std_logic;
signal cSoftwareControl : std_logic_vector(31 downto 0) := (others => '0');
signal dAdcResetPulse : std_logic := '0';
signal dDacResetPulse : std_logic := '0';
constant kSwReset : std_logic := '0';
constant kTimedReset : std_logic := '1';
-- All constants mentioned below are number of the particular clock cycles
-- PllRefClk period. For example, kDataClkCycles is the total number of
-- DataClk cycles in the PllRefClk period.
constant kDataClkCycles : integer := 2;
constant kDataClk2xCycles : integer := 4;
constant kRfClkCycles : integer := 3;
constant kRfClk2xCycles : integer := 6;
constant kConfigPer : time := 25 ns;
-- Make sure the PllRefClk period is a least common multiple of all the other
-- derived clock.
constant kPllRefClkPer : time := 12 ns;
constant kDataClkPer : time := kPllRefClkPer/2;
constant kDataClk2xPer : time := kPllRefClkPer/4;
constant kRfClkPer : time := kPllRefClkPer/3;
constant kRfClk2xPer : time := kPllRefClkPer/6;
signal pReset : boolean := false;
signal dCount : integer := 0;
signal d2Count : integer := 0;
signal rCount : integer := 0;
signal r2Count : integer := 0;
signal StopSim : boolean;
signal ConfigClk : std_logic := '1';
signal RfClk : std_logic := '1';
signal RfClk2x : std_logic := '1';
signal DataClk : std_logic := '1';
signal DataClk2x : std_logic := '1';
signal PllRefClk : std_logic := '1';
signal dAdcDataOutReset_n : std_logic := '0';
signal dAdcDataOutResetDlyd_n : std_logic := '0';
signal dDacDataInReset_n : std_logic := '0';
signal dDacDataInResetDlyd_n : std_logic := '0';
signal d2DacFirReset_n : std_logic := '0';
signal d2DacFirResetDlyd_n : std_logic := '0';
signal rAdcRfdcAxiReset_n : std_logic := '0';
signal rAdcRfdcAxiResetDlyd_n : std_logic := '0';
signal rDacRfdcAxiReset_n : std_logic := '0';
signal rDacRfdcAxiResetDlyd_n : std_logic := '0';
signal r2AdcFirResetDlyd_n : std_logic := '0';
signal r2DacFirResetDlyd_n : std_logic := '0';
signal ExpectedSwAdcResetDone : std_logic := '0';
signal ExpectedAdcReset : std_logic := '0';
signal ExpectedSwDacResetDone : std_logic := '0';
signal ExpectedDacReset : std_logic := '0';
signal ExpectedAxiAdcResetOut : std_logic := '0';
signal ExpectedAxiDacResetOut : std_logic := '0';
-- Make sure the wait time for reset done check is at least 10 ConfigClk
-- cycles to account for all clock domain crossings. We also have some status
-- check in the testbench which requires the wait to be additional ConfigClk
-- cycles. This wait is in ConfigClk period.
constant kResetDoneWait : positive := 10;
procedure ClkWait(signal clk : in std_logic; X : positive := 1) is
begin
for i in 1 to X loop
wait until rising_edge(clk);
end loop;
end procedure ClkWait;
-- Check phase alignment of reset. We want to make sure the reset is asserted
-- on the 1st rising clock edge after the rising edge of PllRefClk.
procedure CheckAlignment(
signal Clk : in std_logic; -- Synchronous reset clock
signal Reset_n : in std_logic; -- Synchronous reset
signal ResetDlyd_n : inout std_logic; -- Delayed synchronous reset
signal PhaseCount : in integer; -- Phase count used to check alignment
Message : string) is -- Assertion message
begin
-- Check if reset is asserted on the 1st Clk after the rising edge of
-- PllRefClk.
if falling_edge(Clk) then
ResetDlyd_n <= Reset_n;
if Reset_n = '0' and ResetDlyd_n = '1' then
assert PhaseCount = 1
report Message & " reset is not asserted in the expected time" severity error;
end if;
end if;
end procedure CheckAlignment;
-- Procedure to generate phase counter that is used to check the alignment of
-- phase of all clocks related to PllRefClk.
procedure PhaseCounter(
signal Clk : in std_logic; -- Clock related to PllRefClk
signal Reset : in boolean; -- Reset synchronous to PllRefClk
signal PhaseCount : inout integer; -- Phase count of Clk with respect to PllRefClk
ClockCycles : integer) is -- Number of Clk clock cycles in PllRefClk period
begin
if rising_edge(Clk) then
if Reset or PhaseCount = ClockCycles-1 then
PhaseCount <= 0;
else
PhaseCount <= PhaseCount+1;
end if;
end if;
end procedure PhaseCounter;
procedure CheckExpectedValue(
signal Clk : in std_logic;
signal Actual : in std_logic;
signal Expected : in std_logic;
Message : string) is
begin
if falling_edge(Clk) then
-- Check if the actual value is as expected.
assert std_match(Actual, Expected)
report Message & " not as expected" & LF
& "Expected = " & std_logic'image(Expected) & LF
& "Actual = " & std_logic'image(Actual) severity error;
end if;
end procedure CheckExpectedValue;
begin
ConfigClk <= not ConfigClk after kConfigPer/2 when not StopSim else '0';
RfClk <= not RfClk after kRfClkPer/2 when not StopSim else '0';
RfClk2x <= not RfClk2x after kRfClk2xPer/2 when not StopSim else '0';
DataClk <= not DataClk after kDataClkPer/2 when not StopSim else '0';
DataClk2x <= not DataClk2x after kDataClk2xPer/2 when not StopSim else '0';
PllRefClk <= not PllRefClk after kPllRefClkPer/2 when not StopSim else '0';
-- rAdcEnableData is a constant and is not tested.
dut: rf_reset_controller
port map (
ConfigClk => ConfigClk,
DataClk => DataClk,
PllRefClk => PllRefClk,
RfClk => RfClk,
RfClk2x => RfClk2x,
DataClk2x => DataClk2x,
dAdcResetPulse => dAdcResetPulse,
dDacResetPulse => dDacResetPulse,
dAdcDataOutReset_n => dAdcDataOutReset_n,
r2AdcFirReset_n => r2AdcFirReset_n,
rAdcRfdcAxiReset_n => rAdcRfdcAxiReset_n,
rAdcEnableData => open,
rAdcGearboxReset_n => rAdcGearboxReset_n,
dDacDataInReset_n => dDacDataInReset_n,
r2DacFirReset_n => r2DacFirReset_n,
d2DacFirReset_n => d2DacFirReset_n,
rDacRfdcAxiReset_n => rDacRfdcAxiReset_n,
rDacGearboxReset_n => rDacGearboxReset_n,
cSoftwareControl => cSoftwareControl,
cSoftwareStatus => cSoftwareStatus
);
main: process
-- Procedure to generate software reset and expected DUR reset output.
procedure StrobeReset(
signal TimedReset : out std_logic; -- SW Reset control
signal ExpectedResetOut : out std_logic; -- Expected reset values
signal ExpectedAxiResetOut : out std_logic; -- Expected reset values
signal SwResetStatus : out std_logic; -- Expected SW reset status
SwReset : integer; -- SW Reset control
ResetType : std_logic; -- 0 = SW reset, 1 = UHD timed reset
ResetWait : positive := 1) is -- Wait time for test iteration
begin
if ResetType = kSwReset then
-- Assert software reset control on the rising edge of ConfigClk. Also
-- change the expected status to don't care as the status will change
-- only after few ConfigClk period.
ClkWait(ConfigClk);
TimedReset <= '0';
cSoftwareControl(SwReset) <= '1';
SwResetStatus <= '-';
ExpectedResetOut <= '-';
ExpectedAxiResetOut <= '-';
ClkWait(ConfigClk, 1);
SwResetStatus <= '0';
-- Wait for additional ConfigClk before changing the expected reset
-- value to '0'. This wait is needed to account for pipeline and clock
-- crossing delays.
ClkWait(ConfigClk, 1);
-- Changed expected reset output to '0' (active low).
ExpectedResetOut <= '0';
ExpectedAxiResetOut <= '0';
ClkWait(ConfigClk,1);
-- SW reset status should be asserted after 3 ConfigClk periods. This
-- wait is needed to account for pipeline and clock crossings.
SwResetStatus <= '1';
-- De-assert software reset
ClkWait(ConfigClk,2);
cSoftwareControl(SwReset) <= '0';
-- Change the expected reset outputs to don't care as it will take few
-- PllRefClk cycles and ConfigClk to DataClock crossing.
ExpectedAxiResetOut <= '-';
ClkWait(ConfigClk,1);
ExpectedAxiResetOut <= '1';
-- After few ConfigClk cycles, all reset outputs should be de-asserted.
ClkWait(ConfigClk,1);
ExpectedResetOut <= '-';
ClkWait(ConfigClk,2);
ExpectedResetOut <= '1';
-- Wait for ResetWait time before exiting the test iteration.
ClkWait(ConfigClk,ResetWait);
else -- Timed command.
ClkWait(DataClk,ResetWait);
TimedReset <= '1';
-- RFDC should not be asserted with timed reset.
ExpectedAxiResetOut <= '1';
-- Strobe the reset pulse only for one DataClk period.
ClkWait(DataClk,1);
TimedReset <= '0';
ClkWait(PllRefClk,2);
ExpectedResetOut <= '-';
-- Wait for 3 PllRefClk to account for pipeline delays.
ClkWait(PllRefClk,1);
ExpectedResetOut <= '0';
ClkWait(PllRefClk,2);
ExpectedResetOut <= '-';
-- Reset should be asserted only for two PllRefClk cycles.
ClkWait(PllRefClk,2);
ExpectedResetOut <= '1';
ClkWait(DataClk,ResetWait); -- Wait between test.
end if;
end procedure StrobeReset;
begin
-- Expected power on reset values.
ExpectedAdcReset <= '0';
ExpectedAxiAdcResetOut <= '0';
ExpectedDacReset <= '0';
ExpectedAxiDacResetOut <= '0';
ClkWait(ConfigClk,1);
ClkWait(RfClk,1);
ExpectedAxiAdcResetOut <= '1';
ExpectedAxiDacResetOut <= '1';
ClkWait(ConfigClk,1);
ExpectedAdcReset <= '-';
ExpectedDacReset <= '-';
ClkWait(ConfigClk,1);
ExpectedAdcReset <= '1';
ExpectedDacReset <= '1';
ClkWait(ConfigClk,5);
-- This reset is for simulation to have a common reference to check for
-- clock alignment.
ClkWait(PllRefClk,1);
pReset <= true;
ClkWait(PllRefClk,1);
pReset <= false;
ClkWait(PllRefClk,1);
---------------------------------------------------------------------------
-- Test resets from software
---------------------------------------------------------------------------
-----------------------------------
-- ADC
-----------------------------------
StrobeReset(dAdcResetPulse, ExpectedAdcReset, ExpectedAxiAdcResetOut,
ExpectedSwAdcResetDone, kADC_RESET, kSwReset, kResetDoneWait);
-- Align reset to the rising edge of PllRefClk
ClkWait(PllRefClk,1);
StrobeReset(dAdcResetPulse, ExpectedAdcReset, ExpectedAxiAdcResetOut,
ExpectedSwAdcResetDone, kADC_RESET, kTimedReset, kResetDoneWait);
StrobeReset(dAdcResetPulse, ExpectedAdcReset, ExpectedAxiAdcResetOut,
ExpectedSwAdcResetDone, kADC_RESET, kSwReset, kResetDoneWait);
-- Align reset to the falling edge of PllRefClk.
ClkWait(PllRefClk,1);
ClkWait(DataClk,1);
StrobeReset(dAdcResetPulse, ExpectedAdcReset, ExpectedAxiAdcResetOut,
ExpectedSwAdcResetDone, kADC_RESET, kTimedReset, kResetDoneWait);
-----------------------------------
-- DAC
-----------------------------------
StrobeReset(dDacResetPulse, ExpectedDacReset, ExpectedAxiDacResetOut,
ExpectedSwDacResetDone, kDAC_RESET, kSwReset, kResetDoneWait);
-- Align reset to the rising edge of PllRefClk.
ClkWait(PllRefClk,1);
StrobeReset(dDacResetPulse, ExpectedDacReset, ExpectedAxiDacResetOut,
ExpectedSwDacResetDone, kDAC_RESET, kTimedReset, kResetDoneWait);
StrobeReset(dDacResetPulse, ExpectedDacReset, ExpectedAxiDacResetOut,
ExpectedSwDacResetDone, kDAC_RESET, kSwReset, kResetDoneWait);
-- Align reset to the falling edge of PllRefClk.
ClkWait(PllRefClk,1);
ClkWait(DataClk,1);
StrobeReset(dDacResetPulse, ExpectedDacReset, ExpectedAxiDacResetOut,
ExpectedSwDacResetDone, kDAC_RESET, kTimedReset, kResetDoneWait);
StopSim <= true;
wait;
end process main;
-----------------------------------------------------------------------------
-- Reset from software and UHD timed command
-----------------------------------------------------------------------------
-- Check if the correct resets are getting asserted when UHD timed reset or
-- software reset is asserted. Except for RFDC AXI-S reset all other resets
-- should be strobed for UHD timed reset.
-----------------------------------------------------------------------------
-- Check if the reset done status is getting asserted as expected.
CheckExpectedValue(ConfigClk, cSoftwareStatus(kADC_SEQ_DONE),
ExpectedSwAdcResetDone, "ADC reset done status");
CheckExpectedValue(ConfigClk, cSoftwareStatus(kDAC_SEQ_DONE),
ExpectedSwDacResetDone, "DAC reset done status");
-- Check if resets state in DataClk is as expected.
CheckExpectedValue(DataClk, dAdcDataOutReset_n, ExpectedAdcReset,
"ADC data out reset");
CheckExpectedValue(DataClk, dDacDataInReset_n, ExpectedDacReset,
"DAC data out reset");
-- Check if resets state in DataClk2x is as expected.
CheckExpectedValue(DataClk2x, d2DacFirReset_n, ExpectedDacReset,
"400M interpolator reset");
---- Check if resets state in RfClk2x is as expected.
CheckExpectedValue(RfClk2x, r2AdcFirReset_n, ExpectedAdcReset,
"ADC re-sampler reset");
CheckExpectedValue(RfClk2x, r2DacFirReset_n, ExpectedDacReset,
"DAC re-sampler reset");
---- Check if resets state in RfClk is as expected.
CheckExpectedValue(RfClk, rAdcRfdcAxiReset_n, ExpectedAxiAdcResetOut,
"ADC RFDC AXI-S interface reset");
CheckExpectedValue(RfClk, rDacRfdcAxiReset_n, ExpectedAxiDacResetOut,
"DAC RFDC AXI-S interface reset");
CheckExpectedValue(RfClk, rAdcGearboxReset_n, ExpectedAdcReset,
"ADC gearbox reset");
CheckExpectedValue(RfClk, rDacGearboxReset_n, ExpectedDacReset,
"DAC gearbox reset");
-----------------------------------------------------------------------------
-- Reset alignment checks for resets
-----------------------------------------------------------------------------
-----------------------------------
-- Clock counter
-----------------------------------
-- We use counters to check the phase of all the derived clocks with respect
-- to PllRefClk. Each counter will rollover at the rising edge of PllRefClk.
-----------------------------------
PhaseCounter(DataClk, pReset, dCount, kDataClkCycles);
PhaseCounter(DataClk2x, pReset, d2Count, kDataClk2xCycles);
PhaseCounter(RfClk, pReset, rCount, kRfClkCycles);
PhaseCounter(RfClk2x, pReset, r2Count, kRfClk2xCycles);
-- Check for DataClk based synchronous reset alignment to PllRefClk.
CheckAlignment(DataClk, dAdcDataOutReset_n, dAdcDataOutResetDlyd_n, dCount,
"ADC data out");
CheckAlignment(DataClk, dDacDataInReset_n, dDacDataInResetDlyd_n, dCount,
"DAC data in");
-- Check for DataClk2x based synchronous reset alignment to PllRefClk.
CheckAlignment(DataClk2x, d2DacFirReset_n, d2DacFirResetDlyd_n, d2Count,
"400M DAC FIR Filter");
-- Check for RfClk based synchronous reset alignment to PllRefClk.
CheckAlignment(RfClk, rAdcRfdcAxiReset_n, rAdcRfdcAxiResetDlyd_n, rCount,
"ADC RFDC reset ");
CheckAlignment(RfClk, rDacRfdcAxiReset_n, rDacRfdcAxiResetDlyd_n, rCount,
"DAC RFDC reset ");
-- Check for RfClk2x based synchronous reset alignment to PllRefClk.
CheckAlignment(RfClk2x, r2AdcFirReset_n, r2AdcFirResetDlyd_n, r2Count,
"ADC decimation filter reset ");
CheckAlignment(RfClk2x, r2DacFirReset_n, r2DacFirResetDlyd_n, r2Count,
"DAC interpolation filter reset ");
end RTL;