1
+ -- This Source Code Form is subject to the terms of the Mozilla Public
2
+ -- License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ -- file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
+ --
5
+ -- Copyright 2025 Oxide Computer Company
6
+
7
+ library ieee;
8
+ use ieee.std_logic_1164.all ;
9
+ use ieee.numeric_std_unsigned.all ;
10
+
11
+ library osvvm;
12
+ use osvvm.RandomPkg.RandomPType;
13
+
14
+ library vunit_lib;
15
+ context vunit_lib.com_context;
16
+ context vunit_lib.vunit_context;
17
+ context vunit_lib.vc_context;
18
+
19
+ -- VCs
20
+ use work.basic_stream_pkg.all ;
21
+ use work.i2c_cmd_vc_pkg.all ;
22
+ use work.i2c_common_pkg.all ;
23
+ use work.i2c_ctrl_vc_pkg.all ;
24
+ use work.i2c_target_vc_pkg.all ;
25
+
26
+ use work.spd_proxy_top_tb_pkg.all ;
27
+
28
+ entity spd_proxy_top_tb is
29
+ generic (
30
+ runner_cfg : string
31
+ );
32
+ end entity ;
33
+
34
+ architecture tb of spd_proxy_top_tb is
35
+ begin
36
+
37
+ th : entity work .spd_proxy_top_th;
38
+
39
+ bench: process
40
+ alias reset is << signal th.reset : std_logic >> ;
41
+ variable rnd : RandomPType;
42
+ variable i2c_ctrlr_msg : msg_t;
43
+
44
+ variable command : cmd_t;
45
+ variable ack : boolean := false ;
46
+
47
+ variable data : std_logic_vector (7 downto 0 );
48
+ variable exp_addr : std_logic_vector (7 downto 0 );
49
+ variable exp_data : std_logic_vector (7 downto 0 );
50
+ variable byte_len : natural ;
51
+ variable byte_idx : natural ;
52
+
53
+ variable cpu_tx_q : queue_t := new_queue;
54
+ variable cpu_ack_q : queue_t := new_queue;
55
+ variable fpga_tx_q : queue_t := new_queue;
56
+ variable fpga_exp_q : queue_t := new_queue;
57
+
58
+ -- helper to get the internal FPGA controller doing _something_ before we have the CPU
59
+ -- attempting to interrupt
60
+ procedure init_controller is
61
+ begin
62
+ -- arbitrary for the test
63
+ exp_addr := X"00" ;
64
+ byte_len := 8 ;
65
+ for i in 0 to byte_len - 1 loop
66
+ push_byte(fpga_tx_q, rnd.RandInt(0 , 255 ));
67
+ end loop ;
68
+ fpga_exp_q := copy(fpga_tx_q);
69
+
70
+ -- write some data in
71
+ command := (
72
+ op => WRITE ,
73
+ addr => address(I2C_TGT_VC),
74
+ reg => std_logic_vector (exp_addr),
75
+ len => to_std_logic_vector(byte_len, command.len'length )
76
+ );
77
+ issue_i2c_cmd(net, command, fpga_tx_q);
78
+ end procedure ;
79
+ begin
80
+ -- Always the first thing in the process, set up things for the VUnit test runner
81
+ test_runner_setup(runner, runner_cfg);
82
+ -- Reach into the test harness, which generates and de-asserts reset and hold the
83
+ -- test cases off until we're out of reset. This runs for every test case
84
+ wait until reset = '0' ;
85
+ wait for 500 ns ; -- let the resets propagate
86
+
87
+ while test_suite loop
88
+ if run(" no_cpu_transaction" ) then
89
+ init_controller;
90
+
91
+ byte_idx := to_integer (exp_addr);
92
+ while not is_empty(fpga_exp_q) loop
93
+ data := to_std_logic_vector(pop_byte(fpga_exp_q), data'length );
94
+ exp_addr := to_std_logic_vector(byte_idx, exp_addr'length );
95
+ check_written_byte(net, I2C_TGT_VC, data, exp_addr);
96
+ byte_idx := byte_idx + 1 ;
97
+ end loop ;
98
+
99
+ expect_stop(net, I2C_TGT_VC);
100
+ elsif run(" cpu_transaction" ) then
101
+ -- Get the FPGA controller started on a transaction
102
+ init_controller;
103
+
104
+ -- At some point into the transaction, have the CPU start its own
105
+ wait for rnd.RandInt(500 , 4000 ) * 1 ns ;
106
+
107
+ push_byte(cpu_tx_q, to_integer (rnd.RandSlv(0 , 255 , 8 )));
108
+ i2c_write_txn(net, address(I2C_TGT_VC), cpu_tx_q, cpu_ack_q, I2C_CTRL_VC.p_actor);
109
+
110
+ elsif run(" cpu_with_simulated_start" ) then
111
+ -- Get the FPGA controller started on a transaction
112
+ init_controller;
113
+
114
+ -- At some point into the transaction, have the CPU start its own
115
+ wait for 9500 ns ;
116
+
117
+ push_byte(cpu_tx_q, to_integer (rnd.RandSlv(0 , 255 , 8 )));
118
+ i2c_write_txn(net, address(I2C_TGT_VC), cpu_tx_q, cpu_ack_q, I2C_CTRL_VC.p_actor);
119
+ end if ;
120
+ end loop ;
121
+
122
+ wait for 2 us ;
123
+ test_runner_cleanup(runner);
124
+ wait ;
125
+ end process ;
126
+
127
+ test_runner_watchdog(runner, 10 ms );
128
+
129
+ end architecture ;
0 commit comments