-
Notifications
You must be signed in to change notification settings - Fork 2
/
fx3_tb.vhd
404 lines (320 loc) · 13.6 KB
/
fx3_tb.vhd
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
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
-- Testbench for FX3-FPGA
-- Load Altera libraries for this device
Library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
--use ieee.std_logic_unsigned.all;
--Library cycloneive;
--use cycloneive.cycloneive_components.all;
-- Load VUnit Lib
library vunit_lib;
context vunit_lib.vunit_context;
-- Setup this testbench as an entity
entity fx3_tb is
generic (runner_cfg : string);
end fx3_tb;
-- Create an implementation of this entity
architecture testbench1 of fx3_tb is
constant FX3_WATERMARK : natural := 3;
constant AWESOME_TEST_HEX : std_logic_vector(31 downto 0) := X"A0_C0FFEE";
constant AWESOME_BULK_HEX : std_logic_vector(31 downto 0) := X"00_C0FFEE";
-- Setup the signals on the fx3 block
signal rst_n_in : std_logic; -- Sync Reset
signal clk_in : std_logic; -- Input Clock (50 MHz)
-- FX3
signal fx3_pclk_out : std_logic; -- FX3 Clock (100 MHz)
signal fx3_slcs_n_out : std_logic; -- Chip Select (Active Low)
signal fx3_slrd_n_out : std_logic; -- Read (Active Low)
signal fx3_slwr_n_out : std_logic; -- Write (Active Low)
signal fx3_sloe_n_out : std_logic; -- Output Enable (Active Low)
signal fx3_fifo_address_out : std_logic_vector(1 downto 0); -- FIFO Address Select
signal fx3_flaga_in : std_logic; -- Address 00 DMA Ready (Active Low)
signal fx3_flagb_in : std_logic; -- Address 00 DMA Watermark (Active Low)
signal fx3_flagc_in : std_logic; -- Address 11 DMA Ready (Active Low)
signal fx3_flagd_in : std_logic; -- Address 11 DMA Watermark (Active Low)
signal fx3_pktend_n_out : std_logic; -- End of Packet or Zero Length Packet Signal (Active Low)
signal fx3_fdata_inout : std_logic_vector(31 downto 0); -- The bidirectional data bus
signal fx3_pmode_out : std_logic_vector(1 downto 0); -- Boot-mode Selector
signal fx3_reset_out : std_logic; -- FX3 Reset
-- RX FIFO
signal rx_ready_in : std_logic;
signal rx_data_out : std_logic_vector(31 downto 0);
signal rx_valid_out : std_logic;
-- TX FIFO
signal tx_ready_out : std_logic;
signal tx_data_in : std_logic_vector(31 downto 0);
signal tx_valid_in : std_logic;
-- Test signals
signal rx_fifo_data_count_out : std_logic_vector(8 downto 0);
signal tx_fifo_data_count_out : std_logic_vector(8 downto 0);
-- Setup the vcc signal as 1
signal vcc : std_logic := '1';
begin
-- The device unter test
dut: entity work.fx3
port map (
rst_n_in => rst_n_in,
clk_in => clk_in,
fx3_pclk_out => fx3_pclk_out,
fx3_slcs_n_out => fx3_slcs_n_out,
fx3_slrd_n_out => fx3_slrd_n_out,
fx3_slwr_n_out => fx3_slwr_n_out,
fx3_sloe_n_out => fx3_sloe_n_out,
fx3_fifo_address_out => fx3_fifo_address_out,
fx3_flaga_in => fx3_flaga_in,
fx3_flagb_in => fx3_flagb_in,
fx3_flagc_in => fx3_flagc_in,
fx3_flagd_in => fx3_flagd_in,
fx3_pktend_n_out => fx3_pktend_n_out,
fx3_fdata_inout => fx3_fdata_inout,
fx3_pmode_out => fx3_pmode_out,
fx3_reset_out => fx3_reset_out,
-- RX Fifo
rx_ready_in => rx_ready_in,
rx_data_out => rx_data_out,
rx_valid_out => rx_valid_out,
-- RX Fifo
tx_ready_out => tx_ready_out,
tx_data_in => tx_data_in,
tx_valid_in => tx_valid_in,
-- Test Signals
rx_fifo_data_count_out => rx_fifo_data_count_out,
tx_fifo_data_count_out => tx_fifo_data_count_out
);
-- Setup the 50 MHz clock
clock : process is begin
loop
clk_in <= '0'; wait for 10 ns;
clk_in <= '1'; wait for 10 ns;
end loop;
end process clock;
-- Let's check our work!
main : process
-- ***** -- Supporting Procedures -- ***** --
procedure sleep(constant delay : in natural) is
variable I : integer range 0 to 2048;
begin
I := 0;
while (I < delay) loop
wait until rising_edge(clk_in);
I := I + 1;
end loop;
end procedure sleep;
-- ***** -- Housekeeping Procedures -- ***** --
procedure clear_flags is begin
fx3_flaga_in <= '0';
fx3_flagb_in <= '0';
fx3_flagc_in <= '0';
fx3_flagd_in <= '0';
sleep(1);
end procedure clear_flags;
procedure clear_rx_buffer is begin
rx_ready_in <= '1';
sleep(512);
rx_ready_in <= '0';
end procedure clear_rx_buffer;
procedure read_setup(constant length : in natural) is begin
--clear_rx_buffer;
-- Setup Flags --
fx3_flaga_in <= '0'; -- FX3 not ready to read
fx3_flagb_in <= '0'; -- FX3 not ready to read
fx3_flagc_in <= '1'; -- Set ready flag (Flag C)
if(length > FX3_WATERMARK) then -- Set watermark flag (Flag D)
fx3_flagd_in <= '1'; -- Higher than watermark
else
fx3_flagd_in <= '0'; -- Less than watermark
end if;
wait until not fx3_slrd_n_out; -- Wait for the FPGA to request data
sleep(2); -- 2 cycle latency from SLRDn to data
end procedure read_setup;
-- FX3 is outta' data. Clear the flags.
procedure read_done is begin
fx3_flagd_in <= '0'; -- Clear the watermark, it's ahead of the game
sleep(1); -- FX3 Ready (Flag C) delayed by 2 clock cycles
clear_flags;
sleep(5); -- Allow time to propagate through the FPGA
end procedure read_done;
procedure send_data_from_fx3(constant data : in std_logic_vector(31 downto 0)) is begin
fx3_fdata_inout <= data;
end procedure send_data_from_fx3;
procedure load_tx_fifo(constant value : in std_logic_vector(31 downto 0)) is begin
wait until rising_edge(clk_in);
sleep(1);
tx_data_in <= value;
tx_valid_in <= '1';
sleep(1);
tx_valid_in <= '0';
end procedure load_tx_fifo;
-- ***** -- Test Procedures -- ***** --
procedure check_fx3_bulk_read(constant length : in natural) is
variable data_position : unsigned(7 downto 0) := X"00";
begin
read_setup(length);
for I in 1 to length-1 loop
if(fx3_slrd_n_out = '0') then
send_data_from_fx3(std_logic_vector(data_position) & X"C0FFEE");
data_position := data_position + 1;
sleep(1);
else
sleep(30);
rx_ready_in <= '1';
wait until fx3_slrd_n_out = '0';
end if;
end loop;
read_done;
-- Check output against expected result.
assert rx_data_out = X"00C0FFEE"
report "Mismatch in FX3 to FPGA Bulk Read Test: " &
"FX3 Data = " & integer'image(to_integer(unsigned(AWESOME_BULK_HEX))) & "; " &
"FIFO Data = " & integer'image(to_integer(unsigned(rx_data_out))) & "; " &
"FX3 RX FIFO Size = " & integer'image(to_integer(unsigned(rx_fifo_data_count_out)))
severity error;
-- Verify the FIFO size
assert unsigned(rx_fifo_data_count_out) = to_unsigned(length,9)
report "FPGA FIFO Size is wrong: " &
"Expected Size = " & integer'image(length) & "; Reported Size = " &
integer'image(to_integer(unsigned(rx_fifo_data_count_out)))
severity error;
end procedure check_fx3_bulk_read;
procedure check_fx3_single_read is begin
read_setup(1);
send_data_from_fx3(AWESOME_TEST_HEX);
read_done;
-- Verify the FIFO size
assert unsigned(rx_fifo_data_count_out) = 1
report "FPGA FIFO Size is wrong: " &
"Expected Size = 1; Reported Size = " &
integer'image(to_integer(unsigned(rx_fifo_data_count_out)))
severity error;
-- Check output against expected result.
assert rx_data_out = AWESOME_TEST_HEX
report "Mismatch in FX3 to FPGA Single Read Test: " &
"FX3 Data = " & to_hstring(AWESOME_TEST_HEX) & "; " &
"FIFO Data = " & to_hstring(rx_data_out) & "; " &
"FX3 RX FIFO Size = " & integer'image(to_integer(unsigned(rx_fifo_data_count_out)))
severity error;
end procedure check_fx3_single_read;
procedure check_fx3_single_write(
constant in1 : in std_logic_vector(31 downto 0)) is begin
report "Start of test!";
clear_flags;
report "TX Reported Size = " & integer'image(to_integer(unsigned(tx_fifo_data_count_out)));
load_tx_fifo(in1);
report "TX Reported Size = " & integer'image(to_integer(unsigned(tx_fifo_data_count_out)));
sleep(1);
report "TX Reported Size = " & integer'image(to_integer(unsigned(tx_fifo_data_count_out)));
-- Verify the FIFO size
assert unsigned(tx_fifo_data_count_out) = 1
report "FPGA FIFO Size is wrong: " &
"Expected Size = 1; Reported Size = " &
integer'image(to_integer(unsigned(tx_fifo_data_count_out)))
severity error;
-- FX3 ready to read data
fx3_flaga_in <= '1';
fx3_flagb_in <= '1';
sleep(1);
-- Wait until we send the first chunk
wait until fx3_slwr_n_out <= '0';
assert fx3_fdata_inout = in1
report "Unexpected Result in FIFO to FX3 Check: " &
"FX3 Data = " & integer'image(to_integer(unsigned(fx3_fdata_inout))) & "; " &
"FX3 Data Expected = " & integer'image(to_integer(unsigned(in1)))
severity error;
end procedure check_fx3_single_write;
procedure check_fx3_bulk_write(
constant in1 : in std_logic_vector(31 downto 0);
constant length : in natural) is begin
clear_flags;
sleep(4);
for I in 1 to length loop
load_tx_fifo(std_logic_vector(unsigned(in1)+to_unsigned(I,31)));
end loop;
sleep(4);
-- Verify the FIFO size
report "Size is: " & integer'image(to_integer(unsigned(tx_fifo_data_count_out)));
assert unsigned(tx_fifo_data_count_out) = length
report "FPGA FIFO Size is wrong: " &
"Expected Size = " & integer'image(length) & " Reported Size = " &
integer'image(to_integer(unsigned(tx_fifo_data_count_out)))
severity error;
-- FX3 ready to read data
fx3_flaga_in <= '1';
fx3_flagb_in <= '1';
-- sleep(1);
-- Wait until we send the first chunk
wait until fx3_slwr_n_out <= '0';
for I in 1 to length-1 loop
report "Index: " & integer'image(I) & " Value: " & integer'image(to_integer(unsigned(fx3_fdata_inout)));
sleep(1);
end loop;
assert fx3_fdata_inout = std_logic_vector(unsigned(in1)+to_unsigned(length,32))
report "Unexpected Result in FIFO to FX3 Check: " &
"FX3 Data = " & integer'image(to_integer(unsigned(fx3_fdata_inout))) & "; " &
"FX3 Data Expected = " & integer'image(to_integer(unsigned(in1)+to_unsigned(length,32)))
severity error;
end procedure check_fx3_bulk_write;
procedure check_fx3_bulk_backpressure_write(
constant in1 : in std_logic_vector(31 downto 0);
constant length : in natural) is begin
clear_flags;
for I in 1 to length loop
load_tx_fifo(std_logic_vector(unsigned(in1)+to_unsigned(I,31)));
end loop;
-- FX3 ready to read data
fx3_flaga_in <= '1';
fx3_flagb_in <= '1';
wait until fx3_slwr_n_out <= '0';
sleep(7);
-- Set FX3 Watermark
fx3_flaga_in <= '1';
fx3_flagb_in <= '0';
-- Set FX3 Full flag (Delayed by 3 cycles from watermark)
sleep(3);
clear_flags;
-- Wait a hot second while the usb host reads data
sleep(1000);
-- Ready to read data again!
fx3_flaga_in <= '1';
fx3_flagb_in <= '1';
report "Value: " & integer'image(to_integer(unsigned(tx_fifo_data_count_out)));
wait until fx3_slwr_n_out <= '0';
-- Wait until we send the first chunk
sleep(88);
assert fx3_fdata_inout = std_logic_vector(unsigned(in1)+to_unsigned(length,32))
report "Unexpected Result in FIFO to FX3 Check: " &
"FX3 Data = " & integer'image(to_integer(unsigned(fx3_fdata_inout))) & "; " &
"FX3 Data Expected = " & integer'image(to_integer(unsigned(in1)+to_unsigned(length,32)))
severity error;
end procedure check_fx3_bulk_backpressure_write;
begin
test_runner_setup(runner, runner_cfg); -- Required for vunit
-- Set inputs & inouts or live in the land of U
-- Set-up the FX3 to power on default state
rst_n_in <= '0';
rx_ready_in <= '0';
tx_data_in <= X"0000_0000";
tx_valid_in <= '0';
fx3_flaga_in <= '1';
fx3_flagb_in <= '0';
fx3_flagc_in <= '0';
fx3_flagd_in <= '0';
fx3_fdata_inout <= (Others => 'Z');
wait for 1 ns;
rst_n_in <= '1';
wait for 1 ns;
while test_suite loop
if run("Single FX3 Read Test") then
check_fx3_single_read;
elsif run("Bulk FX3 Read Test") then
check_fx3_bulk_read(100);
elsif run("Single FX3 Write Test") then
check_fx3_single_write(X"2345_6789");
elsif run("Bulk FX3 Write Test") then
check_fx3_bulk_write(X"0000_0000",100);
elsif run("Bulk FX3 Back-Pressure Write Test") then
check_fx3_bulk_backpressure_write(X"0000_0000",100);
end if;
end loop;
test_runner_cleanup(runner); -- Required for vunit
end process main;
end architecture testbench1;