1 |
42 |
Abraxas3d |
library ieee;
|
2 |
|
|
use ieee.std_logic_1164.all;
|
3 |
|
|
use ieee.math_real.all;
|
4 |
|
|
use ieee.numeric_std.all;
|
5 |
|
|
use std.textio.all;
|
6 |
|
|
use ieee.std_logic_textio.all;
|
7 |
|
|
|
8 |
|
|
entity IQGainPhaseCorrection_testbench is
|
9 |
|
|
end entity;
|
10 |
|
|
|
11 |
|
|
|
12 |
|
|
--The read architecture reads I and Q samples from a text file.
|
13 |
|
|
--The values were created by the MATLAB reference model for the design.
|
14 |
|
|
|
15 |
|
|
architecture IQGainPhaseCorrection_testbench_read of IQGainPhaseCorrection_testbench is
|
16 |
|
|
|
17 |
|
|
--declare the DUT as a component.
|
18 |
|
|
component IQGainPhaseCorrection is
|
19 |
|
|
generic(width :natural);
|
20 |
|
|
port(
|
21 |
|
|
clk :in std_logic;
|
22 |
|
|
x1 :in signed(width-1 downto 0);
|
23 |
|
|
y1 :in signed(width-1 downto 0);
|
24 |
|
|
gain_error :out signed(width-1 downto 0);
|
25 |
|
|
gain_lock :out bit;
|
26 |
|
|
phase_error :out signed(width-1 downto 0);
|
27 |
|
|
phase_lock :out bit;
|
28 |
|
|
corrected_x1 :out signed(width-1 downto 0);
|
29 |
|
|
corrected_y1 :out signed(width-1 downto 0)
|
30 |
|
|
);
|
31 |
|
|
end component;
|
32 |
|
|
|
33 |
|
|
|
34 |
|
|
--tell the testbench which architecture we're using.
|
35 |
|
|
--for DUT: IQGainPhaseCorrection use entity IQGainPhaseCorrection_entity(IQGainPhaseCorrection_arch_integer);
|
36 |
|
|
|
37 |
|
|
|
38 |
|
|
|
39 |
|
|
|
40 |
|
|
--provide signals to run the DUT.
|
41 |
|
|
signal clk_tb : std_logic := '0';
|
42 |
|
|
signal clk_tb_delayed : std_logic := '0';
|
43 |
|
|
signal x1_tb : signed(31 downto 0);
|
44 |
|
|
signal y1_tb : signed(31 downto 0);
|
45 |
|
|
signal gain_error_tb : signed(31 downto 0);
|
46 |
|
|
signal gain_lock_tb : bit;
|
47 |
|
|
signal phase_error_tb : signed(31 downto 0);
|
48 |
|
|
signal phase_lock_tb : bit;
|
49 |
|
|
signal corrected_x1_tb : signed(31 downto 0);
|
50 |
|
|
signal corrected_y1_tb : signed(31 downto 0);
|
51 |
|
|
|
52 |
|
|
|
53 |
|
|
|
54 |
|
|
begin
|
55 |
|
|
|
56 |
|
|
--connect the testbench signal to the component
|
57 |
|
|
DUT:IQGainPhaseCorrection
|
58 |
|
|
generic map(
|
59 |
|
|
width => 32
|
60 |
|
|
)
|
61 |
|
|
port map(
|
62 |
|
|
clk => clk_tb_delayed,
|
63 |
|
|
x1 => x1_tb,
|
64 |
|
|
y1 => y1_tb,
|
65 |
|
|
gain_error => gain_error_tb,
|
66 |
|
|
gain_lock => gain_lock_tb,
|
67 |
|
|
phase_error => phase_error_tb,
|
68 |
|
|
phase_lock => phase_lock_tb,
|
69 |
|
|
corrected_x1 => corrected_x1_tb,
|
70 |
|
|
corrected_y1 => corrected_y1_tb
|
71 |
|
|
);
|
72 |
|
|
|
73 |
|
|
|
74 |
|
|
--Read I and Q from a text file created by MATLAB.
|
75 |
|
|
|
76 |
|
|
|
77 |
|
|
--type file_type is file of element_type;
|
78 |
|
|
--
|
79 |
|
|
--the read and endfile operations are implicitly declared as
|
80 |
|
|
--
|
81 |
|
|
--procedure read ( file f : file_type; value : out element_type );
|
82 |
|
|
--function endfile ( file f : file_type ) return boolean;
|
83 |
|
|
|
84 |
|
|
|
85 |
|
|
|
86 |
|
|
READ_I_Q_SAMPLES: process (clk_tb) is
|
87 |
|
|
|
88 |
|
|
--read input data into process using the readline technique
|
89 |
|
|
file I_data : text open READ_MODE is "I_data_octave";
|
90 |
|
|
file Q_data : text open READ_MODE is "Q_data_octave";
|
91 |
|
|
variable incoming : line;
|
92 |
|
|
|
93 |
|
|
|
94 |
|
|
variable local_x1 : real;
|
95 |
|
|
variable local_y1 : real;
|
96 |
|
|
variable int_x1 : integer;
|
97 |
|
|
variable returned_x1 : signed(31 downto 0); --need to parameterize this
|
98 |
|
|
variable int_y1 : integer;
|
99 |
|
|
variable returned_y1 : signed(31 downto 0); --need to parameterize this
|
100 |
|
|
|
101 |
|
|
begin
|
102 |
|
|
|
103 |
|
|
if (clk_tb'event and clk_tb = '1') then
|
104 |
|
|
|
105 |
|
|
if (not endfile(I_data) and not endfile(Q_data)) then
|
106 |
|
|
|
107 |
|
|
readline(I_data, incoming); --read in the first line.
|
108 |
|
|
read(incoming, local_x1); --get the real value from the first line
|
109 |
|
|
report "Reading " & real'image(local_x1) & " from I_data.";
|
110 |
|
|
local_x1 := local_x1/(1.11); --model AGC
|
111 |
|
|
report "AGC applied. Result: " & real'image(local_x1) & ".";
|
112 |
|
|
int_x1 := integer(trunc(local_x1*((2.0**31.0)-1.0))); --scaled
|
113 |
|
|
report "Converted real I_data to the integer " & integer'image(int_x1) & ".";
|
114 |
|
|
returned_x1 := (to_signed(int_x1, 32));
|
115 |
|
|
x1_tb <= returned_x1;
|
116 |
|
|
|
117 |
|
|
readline(Q_data, incoming); --read in the first line.
|
118 |
|
|
read(incoming, local_y1); --get the real value from the first line
|
119 |
|
|
report "Reading " & real'image(local_y1) & " from Q_data.";
|
120 |
|
|
local_y1 := local_y1/(1.11); --model AGC
|
121 |
|
|
report "AGC applied. Result: " & real'image(local_y1) & ".";
|
122 |
|
|
int_y1 := integer(trunc(local_y1*((2.0**31.0)-1.0))); --scaled
|
123 |
|
|
report "Converted real Q_data to the integer " & integer'image(int_y1) & ".";
|
124 |
|
|
returned_y1 := (to_signed(int_y1, 32));
|
125 |
|
|
y1_tb <= returned_y1;
|
126 |
|
|
|
127 |
|
|
else
|
128 |
|
|
file_close(I_data);
|
129 |
|
|
file_close(Q_data);
|
130 |
|
|
end if;
|
131 |
|
|
end if;
|
132 |
|
|
end process READ_I_Q_SAMPLES;
|
133 |
|
|
|
134 |
|
|
|
135 |
|
|
|
136 |
|
|
COMPARE_RESULTS : process (clk_tb) is
|
137 |
|
|
|
138 |
|
|
--compare process output with data file using the readline technique
|
139 |
|
|
file phase_error : text open READ_MODE is "phase_error_estimate_octave";
|
140 |
|
|
file gain_error : text open READ_MODE is "gain_error_estimate_octave";
|
141 |
|
|
variable incoming : line;
|
142 |
|
|
variable filter_delay : natural := 0;
|
143 |
|
|
|
144 |
|
|
variable local_phase_error : real;
|
145 |
|
|
variable int_phase_error : integer;
|
146 |
|
|
variable octave_phase_error : signed(31 downto 0);
|
147 |
|
|
variable local_gain_error : real;
|
148 |
|
|
variable int_gain_error : integer;
|
149 |
|
|
variable octave_gain_error : signed(31 downto 0);
|
150 |
|
|
|
151 |
|
|
begin
|
152 |
|
|
if (clk_tb'event and clk_tb = '1') then
|
153 |
|
|
if filter_delay > 3 then
|
154 |
|
|
if (not endfile(phase_error) and not endfile(gain_error)) then
|
155 |
|
|
--read in a result and compare with testbench result
|
156 |
|
|
readline(phase_error, incoming); --read in the first line.
|
157 |
|
|
read(incoming, local_phase_error); --get the real value from the first line
|
158 |
|
|
report "Phase error from model: " & real'image(local_phase_error) & ".";
|
159 |
|
|
int_phase_error := integer(trunc(local_phase_error*((2.0**31.0)-1.0))); --scaled
|
160 |
|
|
report "Converted real phase_error to the integer " & integer'image(int_phase_error) & ".";
|
161 |
|
|
octave_phase_error := (to_signed(int_phase_error, 32));
|
162 |
|
|
--does the phase error from the block match octave_phase_error?
|
163 |
|
|
|
164 |
|
|
readline(gain_error, incoming); --read in the first line.
|
165 |
|
|
read(incoming, local_gain_error); --get the real value from the first line
|
166 |
|
|
report "Gain error from model: " & real'image(local_gain_error) & ".";
|
167 |
|
|
int_gain_error := integer(trunc(local_gain_error*((2.0**31.0)-1.0))); --scaled
|
168 |
|
|
report "Converted real gain_error to the integer " & integer'image(int_gain_error) & ".";
|
169 |
|
|
octave_gain_error := (to_signed(int_gain_error, 32));
|
170 |
|
|
--does the gain error from the block match octave_gain_error?
|
171 |
|
|
|
172 |
|
|
|
173 |
|
|
|
174 |
|
|
else
|
175 |
|
|
-- file_close(phase_error);
|
176 |
|
|
-- file_close(gain_error);
|
177 |
|
|
end if;
|
178 |
|
|
else
|
179 |
|
|
filter_delay := filter_delay + 1;
|
180 |
|
|
end if;
|
181 |
|
|
end if;
|
182 |
|
|
end process COMPARE_RESULTS;
|
183 |
|
|
|
184 |
|
|
|
185 |
|
|
|
186 |
|
|
|
187 |
|
|
|
188 |
|
|
|
189 |
|
|
DRIVE_CLOCK:process
|
190 |
|
|
begin
|
191 |
|
|
wait for 50 ns;
|
192 |
|
|
clk_tb <= not clk_tb;
|
193 |
|
|
clk_tb_delayed <= not clk_tb_delayed after 1 ns;
|
194 |
|
|
end process;
|
195 |
|
|
|
196 |
|
|
end IQGainPhaseCorrection_testbench_read;
|