fpga: x400: Add support for X410 motherboard FPGA

Co-authored-by: Andrew Moch <Andrew.Moch@ni.com>
Co-authored-by: Daniel Jepson <daniel.jepson@ni.com>
Co-authored-by: Javier Valenzuela <javier.valenzuela@ni.com>
Co-authored-by: Joerg Hofrichter <joerg.hofrichter@ni.com>
Co-authored-by: Kumaran Subramoniam <kumaran.subramoniam@ni.com>
Co-authored-by: Max Köhler <max.koehler@ni.com>
Co-authored-by: Michael Auchter <michael.auchter@ni.com>
Co-authored-by: Paul Butler <paul.butler@ni.com>
Co-authored-by: Wade Fife <wade.fife@ettus.com>
Co-authored-by: Hector Rubio <hrubio@ni.com>


Original-commit: 6d3765605262016a80f71e36357f749ea35cbe5a
This commit is contained in:
Wade Fife
2021-06-10 11:56:58 -05:00
committed by Aaron Rossetto
co-authored by Andrew Moch Daniel Jepson Javier Valenzuela Joerg Hofrichter Kumaran Subramoniam Max Köhler Michael Auchter Paul Butler Hector Rubio
parent bfef20ea45
commit 61782b02d7
205 changed files with 299634 additions and 0 deletions
@@ -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;
@@ -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;
@@ -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;
@@ -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;
@@ -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;
@@ -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;
@@ -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;
@@ -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;
@@ -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;