aboutsummaryrefslogtreecommitdiffstats
path: root/fpga/usrp3/top/x400/rf/testbench/tb_dac_gearbox_12x8.vhd
blob: cde766cbd15fa81697b6a8b47c880e26db0b73ff (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
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;