207 lines
6.5 KiB
VHDL
207 lines
6.5 KiB
VHDL
--
|
|
-- 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;
|