├── 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 | --------------------------------------------------------------------------------