├── data
├── passati.txt
├── non_passati.txt
├── valori_test.txt
└── ram_content.txt
├── README.md
├── Generatore_RAM_2020.py
└── codice_tb.vhd
/data/passati.txt:
--------------------------------------------------------------------------------
1 | Qui verrà sovrascritto - non sono necessarie modifiche
2 |
--------------------------------------------------------------------------------
/data/non_passati.txt:
--------------------------------------------------------------------------------
1 | Qui verrà sovrascritto - non sono necessarie modifiche
2 |
--------------------------------------------------------------------------------
/data/valori_test.txt:
--------------------------------------------------------------------------------
1 | 1) RAM: [1, 97, 17, 117, 55, 68, 44, 36, 100] - output atteso: 152
2 | 2) RAM: [1, 97, 17, 117, 55, 68, 44, 36, 38] - output atteso: 244
3 | 3) RAM: [97, 6, 27, 82, 10, 45, 106, 20, 7] - output atteso: 146
4 | 4) RAM: [103, 76, 48, 96, 21, 112, 52, 8, 57] - output atteso: 57
5 | 5) RAM: [103, 76, 48, 96, 21, 112, 52, 8, 84] - output atteso: 84
6 | 6) RAM: [65, 58, 77, 19, 25, 48, 37, 81, 79] - output atteso: 164
7 | 7) RAM: [69, 43, 15, 103, 120, 64, 82, 26, 55] - output atteso: 55
8 | 8) RAM: [69, 43, 15, 103, 120, 64, 82, 26, 120] - output atteso: 193
9 | 9) RAM: [117, 67, 108, 7, 33, 96, 13, 87, 70] - output atteso: 152
10 | 10) RAM: [74, 34, 123, 90, 58, 107, 44, 68, 96] - output atteso: 96
11 | 11) RAM: [74, 34, 123, 90, 58, 107, 44, 68, 40] - output atteso: 40
12 | 12) RAM: [68, 8, 62, 86, 39, 114, 14, 1, 11] - output atteso: 152
13 | 13) RAM: [54, 85, 25, 38, 69, 89, 97, 12, 84] - output atteso: 84
14 | 14) RAM: [54, 85, 25, 38, 69, 89, 97, 12, 121] - output atteso: 121
15 | 15) RAM: [13, 95, 51, 111, 61, 73, 103, 118, 59] - output atteso: 59
16 | 16) RAM: [61, 40, 110, 73, 105, 33, 26, 78, 16] - output atteso: 16
17 | 17) RAM: [61, 40, 110, 73, 105, 33, 26, 78, 56] - output atteso: 56
18 | 18) RAM: [124, 114, 7, 50, 84, 56, 120, 88, 59] - output atteso: 216
19 | 19) RAM: [72, 5, 20, 59, 88, 53, 113, 64, 76] - output atteso: 76
20 | 20) RAM: [72, 5, 20, 59, 88, 53, 113, 64, 81] - output atteso: 81
21 | 21) RAM: [65, 121, 5, 59, 46, 116, 72, 20, 52] - output atteso: 52
22 | 22) RAM: [59, 11, 42, 93, 84, 20, 114, 38, 35] - output atteso: 35
23 | 23) RAM: [59, 11, 42, 93, 84, 20, 114, 38, 90] - output atteso: 90
24 | 24) RAM: [90, 64, 85, 38, 79, 51, 4, 31, 25] - output atteso: 25
25 | 25) RAM: [117, 11, 97, 102, 37, 112, 32, 21, 42] - output atteso: 42
26 | 26) RAM: [117, 11, 97, 102, 37, 112, 32, 21, 23] - output atteso: 244
27 | 27) RAM: [117, 96, 46, 26, 38, 4, 89, 122, 26] - output atteso: 177
28 | 28) RAM: [64, 47, 3, 105, 115, 122, 56, 32, 100] - output atteso: 100
29 | 29) RAM: [64, 47, 3, 105, 115, 122, 56, 32, 84] - output atteso: 84
30 | 30) RAM: [8, 104, 0, 29, 39, 43, 114, 93, 14] - output atteso: 14
31 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # TB Progetto di Reti - Politecnico di Milano
2 |
3 | Il tb è stato ideato per l'esame dell'anno accademico 2019/2020.
4 |
5 | La memoria RAM fornita nelle specifiche del progetto usa sempre la stessa interfaccia, quindi con buona probabilità il tb sarà utilizzabile anche nei prossimi anni, al peggio apportando qualche modifica.
6 |
7 | L'idea alla base è di automatizzare il testing del codice scritto in modo da non dover pensare quali siano i casi necessari per avere una copertura totale. Possono essere generati casualmente ed eseguiti un qualsiasi numero di test.
8 |
9 | ## File
10 |
11 | * codice_tb.vhd è il codice del tb.
12 | * Generatore_RAM_2020.py genera molteplici inizializzazioni di valori nella RAM e l'output atteso da ogni singolo test.
13 |
14 |
15 | I file txt in /data di interesse per il tb
16 | * ram_content.txt su cui itera il tb per leggere i valori di input.
17 | * passati.txt / non_passati.txt scritto dal tb per i risultati dei test.
18 |
19 | Il file txt in /data non usato dal tb ma utile per il debugging del codice che si sta testando
20 | * valori_test.txt contiene l'elenco numerato dei test eseguiti con i valori della RAM e l'output atteso.
21 |
22 | ## Utilizzo
23 |
24 | Per progetti in anni diversi dal 2019/2020 va riscritto o modificato il generatore in modo da adattarlo alle specifiche. Quello caricato genera 30 test a fini d'esempio, basta modificare l'indice per aumentarli.
25 |
26 | Nel file codice_tb.vhd leggere la prima riga commentata: vanno cambiati i path dei txt in base a dove si decida di salvarli, sconsiglio di metterli nella directory del progetto perchè potrebbe portare ad avere problemi in lettura. Va bene creare una cartelletta sul Desktop.
27 |
28 | Durante la simulazione il tb itera simulando una volta ognuno dei test generati casualmente, legge l'input da ram_content.txt e ne scrive man mano i risultati dividendoli in base all'esito su passati.txt e non_passati.txt.
29 |
30 | Una grande quantità di test (nell'ordine di 105) potrebbe richiedere pochi secondi in simulazione Behavioral e parecchi minuti in simulazione Functional o Timing, garantendo però una copertura praticamente totale dei casi.
31 |
32 | ### Note
33 | Grazie @davidemerli per aver trovato e sistemato un problema con la parte di test sul doppio start.
34 |
35 | Se i prossimi anni qualcuno decidesse di usare il tb e di riadattare il generatore (usando il linguaggio che preferisce) è pregato di mettere i file ram_content.txt a disposizione dei colleghi.
36 |
--------------------------------------------------------------------------------
/Generatore_RAM_2020.py:
--------------------------------------------------------------------------------
1 | import random
2 |
3 | # Generatore di test per l'anno 2019/2020 - per gli anni successivi andra' modificato in funzione delle specifiche di progetto
4 |
5 | def create_wz(): # Inizializza gli indirizzi salvati nella RAM - nel contesto 2019/2020 si chiamano WZ
6 | new_wz = []
7 | k = 0
8 | while k < 8:
9 | d = 0
10 | wz = random.randint(0,124)
11 | for elem in new_wz:
12 | if((elem <= wz <= elem+3) or (wz <= elem <= wz+3)):
13 | d = 1
14 | if not d:
15 | new_wz.append(wz)
16 | k = k + 1
17 | return new_wz
18 |
19 | def create_addr_and_cod(wz_list): # Crea la coppia (input,output atteso)
20 | addr_da_cod = random.randint(0,127)
21 | addr_codificato = "0000"
22 | k = 0
23 | for wz in wz_list:
24 | if(wz <= addr_da_cod <= wz+3):
25 | addr_codificato = list(addr_codificato)
26 | addr_codificato[-((addr_da_cod - wz) + 1)] = "1"
27 | addr_codificato = "".join(addr_codificato)
28 | addr_codificato = "1" + str(bin(k)[2:].zfill(3)) + addr_codificato
29 | k = k + 1
30 | if addr_codificato == "0000":
31 | return addr_da_cod, addr_da_cod
32 | else:
33 | return addr_da_cod, int(addr_codificato, 2)
34 |
35 |
36 | test = []
37 | for i in range(1,11): #Genera 30 test (10*3)
38 | # Test start singolo
39 | new_wz = create_wz()
40 | addr_da_cod, addr_codificato = create_addr_and_cod(new_wz)
41 | addr_da_cod2, addr_codificato2 = create_addr_and_cod(new_wz)
42 | new_wz.append(addr_da_cod)
43 | new_wz.append(0)
44 | new_wz.append(addr_codificato)
45 | test.append(new_wz)
46 |
47 | # Test secondo start
48 | new_wz2 = new_wz[:]
49 | new_wz2[8] = addr_da_cod2
50 | new_wz2[10] = addr_codificato2
51 | test.append(new_wz2)
52 |
53 | # Test reset sincrono
54 | new_wz = create_wz()
55 | addr_da_cod, addr_codificato = create_addr_and_cod(new_wz)
56 | new_test = new_wz
57 | new_test.append(addr_da_cod)
58 | new_test.append(0)
59 | new_test.append(addr_codificato)
60 | test.append(new_test)
61 |
62 | with open('ram_content.txt','w') as w:
63 | for each_test in test:
64 | for elem in each_test:
65 | w.write(str(elem)+"\n")
66 |
67 | with open('valori_test.txt','w') as w:
68 | num = 1
69 | for each_test in test:
70 | w.write(str(num) + ") RAM: " + str(each_test[:-2]) + " - output atteso: " + str(each_test[-1]) +"\n")
71 | num = num + 1
72 |
73 |
--------------------------------------------------------------------------------
/data/ram_content.txt:
--------------------------------------------------------------------------------
1 | 1
2 | 97
3 | 17
4 | 117
5 | 55
6 | 68
7 | 44
8 | 36
9 | 100
10 | 0
11 | 152
12 | 1
13 | 97
14 | 17
15 | 117
16 | 55
17 | 68
18 | 44
19 | 36
20 | 38
21 | 0
22 | 244
23 | 97
24 | 6
25 | 27
26 | 82
27 | 10
28 | 45
29 | 106
30 | 20
31 | 7
32 | 0
33 | 146
34 | 103
35 | 76
36 | 48
37 | 96
38 | 21
39 | 112
40 | 52
41 | 8
42 | 57
43 | 0
44 | 57
45 | 103
46 | 76
47 | 48
48 | 96
49 | 21
50 | 112
51 | 52
52 | 8
53 | 84
54 | 0
55 | 84
56 | 65
57 | 58
58 | 77
59 | 19
60 | 25
61 | 48
62 | 37
63 | 81
64 | 79
65 | 0
66 | 164
67 | 69
68 | 43
69 | 15
70 | 103
71 | 120
72 | 64
73 | 82
74 | 26
75 | 55
76 | 0
77 | 55
78 | 69
79 | 43
80 | 15
81 | 103
82 | 120
83 | 64
84 | 82
85 | 26
86 | 120
87 | 0
88 | 193
89 | 117
90 | 67
91 | 108
92 | 7
93 | 33
94 | 96
95 | 13
96 | 87
97 | 70
98 | 0
99 | 152
100 | 74
101 | 34
102 | 123
103 | 90
104 | 58
105 | 107
106 | 44
107 | 68
108 | 96
109 | 0
110 | 96
111 | 74
112 | 34
113 | 123
114 | 90
115 | 58
116 | 107
117 | 44
118 | 68
119 | 40
120 | 0
121 | 40
122 | 68
123 | 8
124 | 62
125 | 86
126 | 39
127 | 114
128 | 14
129 | 1
130 | 11
131 | 0
132 | 152
133 | 54
134 | 85
135 | 25
136 | 38
137 | 69
138 | 89
139 | 97
140 | 12
141 | 84
142 | 0
143 | 84
144 | 54
145 | 85
146 | 25
147 | 38
148 | 69
149 | 89
150 | 97
151 | 12
152 | 121
153 | 0
154 | 121
155 | 13
156 | 95
157 | 51
158 | 111
159 | 61
160 | 73
161 | 103
162 | 118
163 | 59
164 | 0
165 | 59
166 | 61
167 | 40
168 | 110
169 | 73
170 | 105
171 | 33
172 | 26
173 | 78
174 | 16
175 | 0
176 | 16
177 | 61
178 | 40
179 | 110
180 | 73
181 | 105
182 | 33
183 | 26
184 | 78
185 | 56
186 | 0
187 | 56
188 | 124
189 | 114
190 | 7
191 | 50
192 | 84
193 | 56
194 | 120
195 | 88
196 | 59
197 | 0
198 | 216
199 | 72
200 | 5
201 | 20
202 | 59
203 | 88
204 | 53
205 | 113
206 | 64
207 | 76
208 | 0
209 | 76
210 | 72
211 | 5
212 | 20
213 | 59
214 | 88
215 | 53
216 | 113
217 | 64
218 | 81
219 | 0
220 | 81
221 | 65
222 | 121
223 | 5
224 | 59
225 | 46
226 | 116
227 | 72
228 | 20
229 | 52
230 | 0
231 | 52
232 | 59
233 | 11
234 | 42
235 | 93
236 | 84
237 | 20
238 | 114
239 | 38
240 | 35
241 | 0
242 | 35
243 | 59
244 | 11
245 | 42
246 | 93
247 | 84
248 | 20
249 | 114
250 | 38
251 | 90
252 | 0
253 | 90
254 | 90
255 | 64
256 | 85
257 | 38
258 | 79
259 | 51
260 | 4
261 | 31
262 | 25
263 | 0
264 | 25
265 | 117
266 | 11
267 | 97
268 | 102
269 | 37
270 | 112
271 | 32
272 | 21
273 | 42
274 | 0
275 | 42
276 | 117
277 | 11
278 | 97
279 | 102
280 | 37
281 | 112
282 | 32
283 | 21
284 | 23
285 | 0
286 | 244
287 | 117
288 | 96
289 | 46
290 | 26
291 | 38
292 | 4
293 | 89
294 | 122
295 | 26
296 | 0
297 | 177
298 | 64
299 | 47
300 | 3
301 | 105
302 | 115
303 | 122
304 | 56
305 | 32
306 | 100
307 | 0
308 | 100
309 | 64
310 | 47
311 | 3
312 | 105
313 | 115
314 | 122
315 | 56
316 | 32
317 | 84
318 | 0
319 | 84
320 | 8
321 | 104
322 | 0
323 | 29
324 | 39
325 | 43
326 | 114
327 | 93
328 | 14
329 | 0
330 | 14
331 |
--------------------------------------------------------------------------------
/codice_tb.vhd:
--------------------------------------------------------------------------------
1 |
2 | -- I path da cambiare sono alle righe 67, 92, 93 -
3 |
4 | library IEEE;
5 | use IEEE.STD_LOGIC_1164.ALL;
6 | use IEEE.STD_LOGIC_UNSIGNED.ALL;
7 | use IEEE.NUMERIC_STD.ALL;
8 | use ieee.std_logic_textio.ALL;
9 | use STD.textio.ALL;
10 |
11 | entity project_tb is
12 | end project_tb;
13 |
14 | architecture projecttb of project_tb is
15 | constant c_CLOCK_PERIOD : time := 100 ns;
16 | signal tb_done : std_logic;
17 | signal mem_address : std_logic_vector (15 downto 0) := (others => '0');
18 | signal tb_rst : std_logic := '0';
19 | signal tb_start : std_logic := '0';
20 | signal tb_clk : std_logic := '0';
21 | signal mem_o_data,mem_i_data : std_logic_vector (7 downto 0);
22 | signal enable_wire : std_logic;
23 | signal mem_we : std_logic;
24 |
25 | type ram_type is array (65535 downto 0) of std_logic_vector(7 downto 0);
26 |
27 | signal RAM : ram_type;
28 | signal s_read_done : boolean := false;
29 | signal s_read : boolean := false;
30 |
31 | component project_reti_logiche is
32 | port (
33 | i_clk : in std_logic;
34 | i_start : in std_logic;
35 | i_rst : in std_logic;
36 | i_data : in std_logic_vector(7 downto 0);
37 | o_address : out std_logic_vector(15 downto 0);
38 | o_done : out std_logic;
39 | o_en : out std_logic;
40 | o_we : out std_logic;
41 | o_data : out std_logic_vector (7 downto 0)
42 | );
43 | end component project_reti_logiche;
44 |
45 |
46 | begin
47 | UUT: project_reti_logiche
48 | port map (
49 | i_clk => tb_clk,
50 | i_start => tb_start,
51 | i_rst => tb_rst,
52 | i_data => mem_o_data,
53 | o_address => mem_address,
54 | o_done => tb_done,
55 | o_en => enable_wire,
56 | o_we => mem_we,
57 | o_data => mem_i_data
58 | );
59 |
60 | p_CLK_GEN : process is
61 | begin
62 | wait for c_CLOCK_PERIOD/2;
63 | tb_clk <= not tb_clk;
64 | end process p_CLK_GEN;
65 |
66 | MEM : process(tb_clk)
67 | file read_file : text open read_mode is "DIRECTORY\ram_content.txt"; --<<<<<<<<<<<<<<<<--------------------------------- QUI DA CAMBIARE
68 | variable read_line : line;
69 | variable R : ram_type;
70 | variable handler : integer;
71 | begin
72 | if tb_clk'event and tb_clk = '1' then
73 | if s_read then
74 | for i in 0 to 10 loop
75 | readline(read_file, read_line);
76 | read(read_line, handler);
77 | RAM(i) <= std_logic_vector(to_unsigned( handler , 8));
78 | end loop;
79 | if endfile(read_file) then s_read_done <= true; end if;
80 | elsif enable_wire = '1' then
81 | if mem_we = '1' then
82 | RAM(conv_integer(mem_address)) <= mem_i_data;
83 | mem_o_data <= mem_i_data after 1 ns;
84 | else
85 | mem_o_data <= RAM(conv_integer(mem_address)) after 1 ns;
86 | end if;
87 | end if;
88 | end if;
89 | end process;
90 |
91 | test : process is
92 | file write_file : text open write_mode is "DIRECTORY\passati.txt"; --<<<<<<<<<<<<<<<<--------------------------------- QUI DA CAMBIARE
93 | file err_write_file : text open write_mode is "DIRECTORY\non_passati.txt"; --<<<<<<<<<<<<<<<<--------------------------------- QUI DA CAMBIARE
94 | variable write_line , err_write_line : line;
95 | variable count : integer := 0;
96 | variable errors : boolean := false;
97 | begin
98 | wait for 100 ns;
99 | loop
100 | ------------------------------------------------------ TEST SINGOLO START ------------------------------------------------------
101 | count := count + 1;
102 | if (s_read_done) then exit; end if;
103 | s_read <= true; -- richiesta di modifica valori ram
104 | wait for c_CLOCK_PERIOD;
105 | s_read <= false;
106 | wait for c_CLOCK_PERIOD;
107 | tb_rst <= '1';
108 | wait for c_CLOCK_PERIOD;
109 | tb_rst <= '0';
110 | wait for c_CLOCK_PERIOD;
111 | tb_start <= '1';
112 | wait for c_CLOCK_PERIOD;
113 | wait until tb_done = '1';
114 | wait for c_CLOCK_PERIOD;
115 | tb_start <= '0';
116 | wait until tb_done = '0';
117 | wait for c_CLOCK_PERIOD;
118 | if(RAM(9) = RAM(10)) then
119 | write(write_line, integer'image(count) & string'(") PASSATO")); --- passati.txt
120 | writeline(write_file, write_line);
121 | else
122 | write(err_write_line, integer'image(count) & string'(") NON PASSATO con risultato ")& integer'image(to_integer(unsigned(RAM(9)))) & string'(" - Caso start singolo")); --- non_passati.txt
123 | writeline(err_write_file, err_write_line);
124 | errors := true;
125 | end if;
126 | ------------------------------------------------------ TEST SECONDO START (cambia addr da cod, no wz) ------------------------------------------------------
127 | wait for c_CLOCK_PERIOD;
128 | count := count + 1;
129 | if (s_read_done) then exit; end if;
130 | s_read <= true; -- richiesta di modifica valori ram
131 | wait for c_CLOCK_PERIOD;
132 | s_read <= false;
133 | wait for c_CLOCK_PERIOD;
134 | tb_start <= '1';
135 | wait for c_CLOCK_PERIOD;
136 | wait until tb_done = '1';
137 | wait for c_CLOCK_PERIOD;
138 | tb_start <= '0';
139 | wait until tb_done = '0';
140 | wait for c_CLOCK_PERIOD;
141 | if(RAM(9) = RAM(10)) then
142 | write(write_line, integer'image(count) & string'(") PASSATO")); --- passati.txt
143 | writeline(write_file, write_line);
144 | else
145 | write(err_write_line, integer'image(count) & string'(") NON PASSATO con risultato ")& integer'image(to_integer(unsigned(RAM(9)))) & string'(" - Secondo start, per riferimento primo start guardare test ") & integer'image(count-1)); --- non_passati.txt
146 | writeline(err_write_file, err_write_line);
147 | errors := true;
148 | end if;
149 | ------------------------------------------------------ TEST RESET SINCRONO (dopo 4 clk) ------------------------------------------------------
150 | count := count + 1;
151 | if (s_read_done) then exit; end if;
152 | s_read <= true; -- richiesta di modifica valori ram
153 | wait for c_CLOCK_PERIOD;
154 | s_read <= false;
155 | wait for c_CLOCK_PERIOD;
156 | tb_rst <= '1';
157 | wait for c_CLOCK_PERIOD;
158 | tb_rst <= '0';
159 | wait for c_CLOCK_PERIOD;
160 | tb_start <= '1';
161 | wait for c_CLOCK_PERIOD;
162 | wait for c_CLOCK_PERIOD;
163 | wait for c_CLOCK_PERIOD;
164 | wait for c_CLOCK_PERIOD;
165 | tb_rst <= '1';
166 | wait for c_CLOCK_PERIOD;
167 | tb_rst <= '0';
168 | wait for c_CLOCK_PERIOD;
169 | wait until tb_done = '1';
170 | wait for c_CLOCK_PERIOD;
171 | tb_start <= '0';
172 | wait until tb_done = '0';
173 | wait for c_CLOCK_PERIOD;
174 | if(RAM(9) = RAM(10)) then
175 | write(write_line, integer'image(count) & string'(") PASSATO")); --- passati.txt
176 | writeline(write_file, write_line);
177 | else
178 | write(err_write_line, integer'image(count) & string'(") NON PASSATO con risultato ")& integer'image(to_integer(unsigned(RAM(9)))) & string'(" - Test reset asincrono dopo 4 clk")); --- non_passati.txt
179 | writeline(err_write_file, err_write_line);
180 | errors := true;
181 | end if;
182 | ---------- fine casi di test ----------
183 | end loop;
184 | if(not errors) then
185 | write(err_write_line, string'("Tutti i test sono stati passati"));
186 | writeline(err_write_file, err_write_line);
187 | end if;
188 | file_close(write_file);
189 | file_close(err_write_file);
190 | std.env.finish;
191 | end process test;
192 |
193 | end projecttb;
194 |
--------------------------------------------------------------------------------