198 lines
5.8 KiB
VHDL
198 lines
5.8 KiB
VHDL
--
|
|
-- 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;
|