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 2024 Oxide Computer Company
6
+
7
+ library ieee;
8
+ use ieee.std_logic_1164.all ;
9
+ use ieee.numeric_std.all ;
10
+ use ieee.numeric_std_unsigned.all ;
11
+
12
+ library vunit_lib;
13
+ context vunit_lib.com_context;
14
+ context vunit_lib.vunit_context;
15
+ context vunit_lib.vc_context;
16
+
17
+ use vunit_lib.spi_pkg.all ;
18
+
19
+ use work.spi_axi_tb_pkg.all ;
20
+ use work.spi_axi_pkg.all ;
21
+
22
+
23
+ entity spi_axi_tb is
24
+ generic (
25
+
26
+ runner_cfg : string
27
+ );
28
+ end entity ;
29
+
30
+ architecture tb of spi_axi_tb is
31
+
32
+ begin
33
+
34
+ th : entity work .spi_axi_th;
35
+
36
+ bench: process
37
+ alias reset is << signal th.reset : std_logic >> ;
38
+ alias csn is << signal th.csn : std_logic >> ;
39
+ variable buf : buffer_t;
40
+ variable buf2 : buffer_t;
41
+ variable data : std_logic_vector (7 downto 0 ) := (others => '0' );
42
+ variable expected_data : std_logic_vector (7 downto 0 ) := (others => '0' );
43
+ variable address : std_logic_vector (15 downto 0 ) := (others => '0' );
44
+ alias addr_h : std_logic_vector (7 downto 0 ) is address(15 downto 8 );
45
+ alias addr_l : std_logic_vector (7 downto 0 ) is address(7 downto 0 );
46
+ begin
47
+ -- Always the first thing in the process, set up things for the VUnit test runner
48
+ test_runner_setup(runner, runner_cfg);
49
+ show_all(wr_logger, display_handler);
50
+ -- Reach into the test harness, which generates and de-asserts reset and hold the
51
+ -- test cases off until we're out of reset. This runs for every test case
52
+ wait until reset = '0' ;
53
+ wait for 500 ns ; -- let the resets propagate
54
+
55
+ while test_suite loop
56
+ if run(" single-read" ) then
57
+ -- set up the "memory to be read with a known value"
58
+ buf := allocate(rmemory, 1 * 64 , alignment => 8 );
59
+ -- Use the simulation interface to set the data we're going to read back
60
+ expected_data := X"AA" ;
61
+ write_word(rmemory, 0 , expected_data);
62
+ -- TB will fault if DUT tries to write to this memory
63
+ set_permissions(rmemory, 0 , read_only);
64
+ -- issue spi read command (data is dummy byte here since this is a)
65
+ spi_send_byte(net, spi_opcode_read, address, (others => '0' ), csn);
66
+ -- Read back word rx'd from DUT and check it matches expected.
67
+ -- -- we're going to have 3 dummy bytes here, skip them, keeping the 4th
68
+ for i in 0 to 3 loop
69
+ pop_stream(net, master_rstream, data);
70
+ end loop ;
71
+ check_equal(data, expected_data, " Read data did not match expected" );
72
+ elsif run(" single-write" ) then
73
+ -- set up the "memory to be read with a known value"
74
+ buf := allocate(wmemory, 1 * 64 , alignment => 8 );
75
+ -- Use the simulation interface to set the data we're expected to write
76
+ expected_data := X"AA" ;
77
+ set_expected_word(wmemory, 0 , expected_data);
78
+ -- issue spi write command
79
+ spi_send_byte(net, spi_opcode_write, address, expected_data, csn);
80
+ -- no reach into the ram and see what is there now
81
+ wait for 20 ns ;
82
+ check_expected_was_written(buf);
83
+ elsif run(" single-bit-set" ) then
84
+ -- Due to how the axi blocks by vunit work, we need to set up 2 buffers, one for the
85
+ -- read side and one for the write-side
86
+ -- READ SIDE is buf
87
+ -- set up the "memory to be read with a known value"
88
+ buf := allocate(rmemory, 1 * 64 , alignment => 8 );
89
+ -- WRITE SIDE is buf2
90
+ buf2 := allocate(wmemory, 1 * 64 , alignment => 8 );
91
+ -- Sick X"AA" into the read buffer, this is going to be our starting point for the bit-set
92
+ -- Use the simulation interface to set the data we're going to read back
93
+ expected_data := X"AA" ;
94
+ write_word(rmemory, 0 , expected_data);
95
+ -- Our Write address now has X"AA" in it.
96
+ data := X"05" ;
97
+ -- This is the expected write into the write-side after the read-modify-write bit-set operation
98
+ expected_data := expected_data or data;
99
+ set_expected_word(wmemory, 0 , expected_data);
100
+
101
+ -- issue spi write command for bit set with data bits
102
+ spi_send_byte(net, spi_opcode_bit_set, address, data, csn);
103
+
104
+ -- no reach into the ram and see what is there now
105
+ wait for 1 us ;
106
+ check_expected_was_written(buf2);
107
+ elsif run(" single-bit-clr" ) then
108
+ -- Due to how the axi blocks by vunit work, we need to set up 2 buffers, one for the
109
+ -- read side and one for the write-side
110
+ -- READ SIDE is buf
111
+ -- set up the "memory to be read with a known value"
112
+ buf := allocate(rmemory, 1 * 64 , alignment => 8 );
113
+ -- WRITE SIDE is buf2
114
+ buf2 := allocate(wmemory, 1 * 64 , alignment => 8 );
115
+ -- Sick X"AA" into the read buffer, this is going to be our starting point for the bit-set
116
+
117
+ -- Use the simulation interface to set the data we're going to read back
118
+ expected_data := X"AA" ;
119
+ write_word(rmemory, 0 , expected_data);
120
+ -- Our Write address now has X"AA" in it.
121
+ data := X"0A" ;
122
+ -- This is the expected write into the write-side after the read-modify-write bit-set operation
123
+ expected_data := expected_data and (not data);
124
+ set_expected_word(wmemory, 0 , expected_data);
125
+
126
+ -- issue spi write command for bit set with data bits
127
+ spi_send_byte(net, spi_opcode_bit_clr, address, data, csn);
128
+ -- no reach into the ram and see what is there now
129
+ wait for 20 ns ;
130
+ check_expected_was_written(buf2);
131
+
132
+ -- multi-read
133
+ -- multi-write
134
+ -- Note: by and large, multi-bit-set/clr doesn't really make sense over this interface
135
+ -- it may still work, do we need to test it?
136
+ -- invalid transaction, ok after
137
+ -- early termination of transaction, ok after
138
+ end if ;
139
+ end loop ;
140
+
141
+ wait for 2 us ;
142
+ test_runner_cleanup(runner);
143
+ wait ;
144
+ end process ;
145
+
146
+ -- Example total test timeout dog
147
+ test_runner_watchdog(runner, 10 ms );
148
+
149
+ end tb;
0 commit comments