Make divider hang off the side of execute1
[microwatt.git] / divider_tb.vhdl
1 library ieee;
2 use ieee.std_logic_1164.all;
3 use ieee.numeric_std.all;
4
5 library work;
6 use work.decode_types.all;
7 use work.common.all;
8 use work.glibc_random.all;
9 use work.ppc_fx_insns.all;
10
11 entity divider_tb is
12 end divider_tb;
13
14 architecture behave of divider_tb is
15 signal clk : std_ulogic;
16 signal rst : std_ulogic;
17 constant clk_period : time := 10 ns;
18
19 signal d1 : Execute1ToDividerType;
20 signal d2 : DividerToExecute1Type;
21 begin
22 divider_0: entity work.divider
23 port map (clk => clk, rst => rst, d_in => d1, d_out => d2);
24
25 clk_process: process
26 begin
27 clk <= '0';
28 wait for clk_period/2;
29 clk <= '1';
30 wait for clk_period/2;
31 end process;
32
33 stim_process: process
34 variable ra, rb, rt, behave_rt: std_ulogic_vector(63 downto 0);
35 variable si: std_ulogic_vector(15 downto 0);
36 variable d128: std_ulogic_vector(127 downto 0);
37 variable q128: std_ulogic_vector(127 downto 0);
38 variable q64: std_ulogic_vector(63 downto 0);
39 variable rem32: std_ulogic_vector(31 downto 0);
40 begin
41 rst <= '1';
42 wait for clk_period;
43 rst <= '0';
44
45 d1.valid <= '1';
46 d1.write_reg <= "10001";
47 d1.dividend <= x"0000000010001000";
48 d1.divisor <= x"0000000000001111";
49 d1.is_signed <= '0';
50 d1.is_32bit <= '0';
51 d1.is_extended <= '0';
52 d1.is_modulus <= '0';
53 d1.neg_result <= '0';
54 d1.rc <= '0';
55
56 wait for clk_period;
57 assert d2.valid = '0';
58
59 d1.valid <= '0';
60
61 for j in 0 to 66 loop
62 wait for clk_period;
63 if d2.valid = '1' then
64 exit;
65 end if;
66 end loop;
67
68 assert d2.valid = '1';
69 assert d2.write_reg_nr = "10001";
70 assert d2.write_reg_data = x"000000000000f001" report "result " & to_hstring(d2.write_reg_data);
71 assert d2.rc = '0';
72
73 wait for clk_period;
74 assert d2.valid = '0' report "valid";
75
76 d1.valid <= '1';
77 d1.rc <= '1';
78
79 wait for clk_period;
80 assert d2.valid = '0' report "valid";
81
82 d1.valid <= '0';
83
84 for j in 0 to 66 loop
85 wait for clk_period;
86 if d2.valid = '1' then
87 exit;
88 end if;
89 end loop;
90
91 assert d2.valid = '1';
92 assert d2.write_reg_nr = "10001";
93 assert d2.write_reg_data = x"000000000000f001" report "result " & to_hstring(d2.write_reg_data);
94 assert d2.rc = '1';
95
96 wait for clk_period;
97 assert d2.valid = '0';
98
99 -- test divd
100 report "test divd";
101 divd_loop : for dlength in 1 to 8 loop
102 for vlength in 1 to dlength loop
103 for i in 0 to 100 loop
104 ra := std_ulogic_vector(resize(signed(pseudorand(dlength * 8)), 64));
105 rb := std_ulogic_vector(resize(signed(pseudorand(vlength * 8)), 64));
106
107 d1.dividend <= ra when ra(63) = '0' else std_ulogic_vector(- signed(ra));
108 d1.divisor <= rb when rb(63) = '0' else std_ulogic_vector(- signed(rb));
109 d1.is_signed <= '1';
110 d1.neg_result <= ra(63) xor rb(63);
111 d1.valid <= '1';
112
113 wait for clk_period;
114
115 d1.valid <= '0';
116 for j in 0 to 66 loop
117 wait for clk_period;
118 if d2.valid = '1' then
119 exit;
120 end if;
121 end loop;
122 assert d2.valid = '1';
123
124 behave_rt := (others => '0');
125 if rb /= x"0000000000000000" and (ra /= x"8000000000000000" or rb /= x"ffffffffffffffff") then
126 behave_rt := ppc_divd(ra, rb);
127 end if;
128 assert to_hstring(behave_rt) = to_hstring(d2.write_reg_data)
129 report "bad divd expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data);
130 end loop;
131 end loop;
132 end loop;
133
134 -- test divdu
135 report "test divdu";
136 divdu_loop : for dlength in 1 to 8 loop
137 for vlength in 1 to dlength loop
138 for i in 0 to 100 loop
139 ra := std_ulogic_vector(resize(unsigned(pseudorand(dlength * 8)), 64));
140 rb := std_ulogic_vector(resize(unsigned(pseudorand(vlength * 8)), 64));
141
142 d1.dividend <= ra;
143 d1.divisor <= rb;
144 d1.is_signed <= '0';
145 d1.neg_result <= '0';
146 d1.valid <= '1';
147
148 wait for clk_period;
149
150 d1.valid <= '0';
151 for j in 0 to 66 loop
152 wait for clk_period;
153 if d2.valid = '1' then
154 exit;
155 end if;
156 end loop;
157 assert d2.valid = '1';
158
159 behave_rt := (others => '0');
160 if rb /= x"0000000000000000" then
161 behave_rt := ppc_divdu(ra, rb);
162 end if;
163 assert to_hstring(behave_rt) = to_hstring(d2.write_reg_data)
164 report "bad divdu expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data);
165 end loop;
166 end loop;
167 end loop;
168
169 -- test divde
170 report "test divde";
171 divde_loop : for vlength in 1 to 8 loop
172 for dlength in 1 to vlength loop
173 for i in 0 to 100 loop
174 ra := std_ulogic_vector(resize(signed(pseudorand(dlength * 8)), 64));
175 rb := std_ulogic_vector(resize(signed(pseudorand(vlength * 8)), 64));
176
177 d1.dividend <= ra when ra(63) = '0' else std_ulogic_vector(- signed(ra));
178 d1.divisor <= rb when rb(63) = '0' else std_ulogic_vector(- signed(rb));
179 d1.is_signed <= '1';
180 d1.neg_result <= ra(63) xor rb(63);
181 d1.is_extended <= '1';
182 d1.valid <= '1';
183
184 wait for clk_period;
185
186 d1.valid <= '0';
187 for j in 0 to 66 loop
188 wait for clk_period;
189 if d2.valid = '1' then
190 exit;
191 end if;
192 end loop;
193 assert d2.valid = '1';
194
195 behave_rt := (others => '0');
196 if rb /= x"0000000000000000" then
197 d128 := ra & x"0000000000000000";
198 q128 := std_ulogic_vector(signed(d128) / signed(rb));
199 if q128(127 downto 63) = x"0000000000000000" & '0' or
200 q128(127 downto 63) = x"ffffffffffffffff" & '1' then
201 behave_rt := q128(63 downto 0);
202 end if;
203 end if;
204 assert to_hstring(behave_rt) = to_hstring(d2.write_reg_data)
205 report "bad divde expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data) & " for ra = " & to_hstring(ra) & " rb = " & to_hstring(rb);
206 end loop;
207 end loop;
208 end loop;
209
210 -- test divdeu
211 report "test divdeu";
212 divdeu_loop : for vlength in 1 to 8 loop
213 for dlength in 1 to vlength loop
214 for i in 0 to 100 loop
215 ra := std_ulogic_vector(resize(unsigned(pseudorand(dlength * 8)), 64));
216 rb := std_ulogic_vector(resize(unsigned(pseudorand(vlength * 8)), 64));
217
218 d1.dividend <= ra;
219 d1.divisor <= rb;
220 d1.is_signed <= '0';
221 d1.neg_result <= '0';
222 d1.is_extended <= '1';
223 d1.valid <= '1';
224
225 wait for clk_period;
226
227 d1.valid <= '0';
228 for j in 0 to 66 loop
229 wait for clk_period;
230 if d2.valid = '1' then
231 exit;
232 end if;
233 end loop;
234 assert d2.valid = '1';
235
236 behave_rt := (others => '0');
237 if unsigned(rb) > unsigned(ra) then
238 d128 := ra & x"0000000000000000";
239 q128 := std_ulogic_vector(unsigned(d128) / unsigned(rb));
240 behave_rt := q128(63 downto 0);
241 end if;
242 assert to_hstring(behave_rt) = to_hstring(d2.write_reg_data)
243 report "bad divdeu expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data) & " for ra = " & to_hstring(ra) & " rb = " & to_hstring(rb);
244 end loop;
245 end loop;
246 end loop;
247
248 -- test divw
249 report "test divw";
250 divw_loop : for dlength in 1 to 4 loop
251 for vlength in 1 to dlength loop
252 for i in 0 to 100 loop
253 ra := std_ulogic_vector(resize(signed(pseudorand(dlength * 8)), 64));
254 rb := std_ulogic_vector(resize(signed(pseudorand(vlength * 8)), 64));
255
256 d1.dividend <= ra when ra(63) = '0' else std_ulogic_vector(- signed(ra));
257 d1.divisor <= rb when rb(63) = '0' else std_ulogic_vector(- signed(rb));
258 d1.is_signed <= '1';
259 d1.neg_result <= ra(63) xor rb(63);
260 d1.is_extended <= '0';
261 d1.is_32bit <= '1';
262 d1.valid <= '1';
263
264 wait for clk_period;
265
266 d1.valid <= '0';
267 for j in 0 to 66 loop
268 wait for clk_period;
269 if d2.valid = '1' then
270 exit;
271 end if;
272 end loop;
273 assert d2.valid = '1';
274
275 behave_rt := (others => '0');
276 if rb /= x"0000000000000000" and (ra /= x"ffffffff80000000" or rb /= x"ffffffffffffffff") then
277 behave_rt := ppc_divw(ra, rb);
278 end if;
279 assert behave_rt = d2.write_reg_data
280 report "bad divw expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data);
281 end loop;
282 end loop;
283 end loop;
284
285 -- test divwu
286 report "test divwu";
287 divwu_loop : for dlength in 1 to 4 loop
288 for vlength in 1 to dlength loop
289 for i in 0 to 100 loop
290 ra := std_ulogic_vector(resize(unsigned(pseudorand(dlength * 8)), 64));
291 rb := std_ulogic_vector(resize(unsigned(pseudorand(vlength * 8)), 64));
292
293 d1.dividend <= ra;
294 d1.divisor <= rb;
295 d1.is_signed <= '0';
296 d1.neg_result <= '0';
297 d1.is_extended <= '0';
298 d1.is_32bit <= '1';
299 d1.valid <= '1';
300
301 wait for clk_period;
302
303 d1.valid <= '0';
304 for j in 0 to 66 loop
305 wait for clk_period;
306 if d2.valid = '1' then
307 exit;
308 end if;
309 end loop;
310 assert d2.valid = '1';
311
312 behave_rt := (others => '0');
313 if rb /= x"0000000000000000" then
314 behave_rt := ppc_divwu(ra, rb);
315 end if;
316 assert behave_rt = d2.write_reg_data
317 report "bad divwu expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data);
318 end loop;
319 end loop;
320 end loop;
321
322 -- test divwe
323 report "test divwe";
324 divwe_loop : for vlength in 1 to 4 loop
325 for dlength in 1 to vlength loop
326 for i in 0 to 100 loop
327 ra := std_ulogic_vector(resize(signed(pseudorand(dlength * 8)), 32)) & x"00000000";
328 rb := std_ulogic_vector(resize(signed(pseudorand(vlength * 8)), 64));
329
330 d1.dividend <= ra when ra(63) = '0' else std_ulogic_vector(- signed(ra));
331 d1.divisor <= rb when rb(63) = '0' else std_ulogic_vector(- signed(rb));
332 d1.is_signed <= '1';
333 d1.neg_result <= ra(63) xor rb(63);
334 d1.is_extended <= '0';
335 d1.is_32bit <= '1';
336 d1.valid <= '1';
337
338 wait for clk_period;
339
340 d1.valid <= '0';
341 for j in 0 to 66 loop
342 wait for clk_period;
343 if d2.valid = '1' then
344 exit;
345 end if;
346 end loop;
347 assert d2.valid = '1';
348
349 behave_rt := (others => '0');
350 if rb /= x"0000000000000000" then
351 q64 := std_ulogic_vector(signed(ra) / signed(rb));
352 if q64(63 downto 31) = x"00000000" & '0' or
353 q64(63 downto 31) = x"ffffffff" & '1' then
354 behave_rt := x"00000000" & q64(31 downto 0);
355 end if;
356 assert behave_rt = d2.write_reg_data
357 report "bad divwe expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data) & " for ra = " & to_hstring(ra) & " rb = " & to_hstring(rb);
358 end if;
359 end loop;
360 end loop;
361 end loop;
362
363 -- test divweu
364 report "test divweu";
365 divweu_loop : for vlength in 1 to 4 loop
366 for dlength in 1 to vlength loop
367 for i in 0 to 100 loop
368 ra := std_ulogic_vector(resize(unsigned(pseudorand(dlength * 8)), 32)) & x"00000000";
369 rb := std_ulogic_vector(resize(unsigned(pseudorand(vlength * 8)), 64));
370
371 d1.dividend <= ra;
372 d1.divisor <= rb;
373 d1.is_signed <= '0';
374 d1.neg_result <= '0';
375 d1.is_extended <= '0';
376 d1.is_32bit <= '1';
377 d1.valid <= '1';
378
379 wait for clk_period;
380
381 d1.valid <= '0';
382 for j in 0 to 66 loop
383 wait for clk_period;
384 if d2.valid = '1' then
385 exit;
386 end if;
387 end loop;
388 assert d2.valid = '1';
389
390 behave_rt := (others => '0');
391 if unsigned(rb(31 downto 0)) > unsigned(ra(63 downto 32)) then
392 behave_rt := std_ulogic_vector(unsigned(ra) / unsigned(rb));
393 end if;
394 assert behave_rt = d2.write_reg_data
395 report "bad divweu expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data) & " for ra = " & to_hstring(ra) & " rb = " & to_hstring(rb);
396 end loop;
397 end loop;
398 end loop;
399
400 -- test modsd
401 report "test modsd";
402 modsd_loop : for dlength in 1 to 8 loop
403 for vlength in 1 to dlength loop
404 for i in 0 to 100 loop
405 ra := std_ulogic_vector(resize(signed(pseudorand(dlength * 8)), 64));
406 rb := std_ulogic_vector(resize(signed(pseudorand(vlength * 8)), 64));
407
408 d1.dividend <= ra when ra(63) = '0' else std_ulogic_vector(- signed(ra));
409 d1.divisor <= rb when rb(63) = '0' else std_ulogic_vector(- signed(rb));
410 d1.is_signed <= '1';
411 d1.neg_result <= ra(63);
412 d1.is_extended <= '0';
413 d1.is_32bit <= '0';
414 d1.is_modulus <= '1';
415 d1.valid <= '1';
416
417 wait for clk_period;
418
419 d1.valid <= '0';
420 for j in 0 to 66 loop
421 wait for clk_period;
422 if d2.valid = '1' then
423 exit;
424 end if;
425 end loop;
426 assert d2.valid = '1';
427
428 behave_rt := (others => '0');
429 if rb /= x"0000000000000000" then
430 behave_rt := std_ulogic_vector(signed(ra) rem signed(rb));
431 end if;
432 assert behave_rt = d2.write_reg_data
433 report "bad modsd expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data);
434 end loop;
435 end loop;
436 end loop;
437
438 -- test modud
439 report "test modud";
440 modud_loop : for dlength in 1 to 8 loop
441 for vlength in 1 to dlength loop
442 for i in 0 to 100 loop
443 ra := std_ulogic_vector(resize(unsigned(pseudorand(dlength * 8)), 64));
444 rb := std_ulogic_vector(resize(unsigned(pseudorand(vlength * 8)), 64));
445
446 d1.dividend <= ra;
447 d1.divisor <= rb;
448 d1.is_signed <= '0';
449 d1.neg_result <= '0';
450 d1.is_extended <= '0';
451 d1.is_32bit <= '0';
452 d1.is_modulus <= '1';
453 d1.valid <= '1';
454
455 wait for clk_period;
456
457 d1.valid <= '0';
458 for j in 0 to 66 loop
459 wait for clk_period;
460 if d2.valid = '1' then
461 exit;
462 end if;
463 end loop;
464 assert d2.valid = '1';
465
466 behave_rt := (others => '0');
467 if rb /= x"0000000000000000" then
468 behave_rt := std_ulogic_vector(unsigned(ra) rem unsigned(rb));
469 end if;
470 assert behave_rt = d2.write_reg_data
471 report "bad modud expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data);
472 end loop;
473 end loop;
474 end loop;
475
476 -- test modsw
477 report "test modsw";
478 modsw_loop : for dlength in 1 to 4 loop
479 for vlength in 1 to dlength loop
480 for i in 0 to 100 loop
481 ra := std_ulogic_vector(resize(signed(pseudorand(dlength * 8)), 64));
482 rb := std_ulogic_vector(resize(signed(pseudorand(vlength * 8)), 64));
483
484 d1.dividend <= ra when ra(63) = '0' else std_ulogic_vector(- signed(ra));
485 d1.divisor <= rb when rb(63) = '0' else std_ulogic_vector(- signed(rb));
486 d1.is_signed <= '1';
487 d1.neg_result <= ra(63);
488 d1.is_extended <= '0';
489 d1.is_32bit <= '1';
490 d1.is_modulus <= '1';
491 d1.valid <= '1';
492
493 wait for clk_period;
494
495 d1.valid <= '0';
496 for j in 0 to 66 loop
497 wait for clk_period;
498 if d2.valid = '1' then
499 exit;
500 end if;
501 end loop;
502 assert d2.valid = '1';
503
504 behave_rt := (others => '0');
505 if rb /= x"0000000000000000" then
506 rem32 := std_ulogic_vector(signed(ra(31 downto 0)) rem signed(rb(31 downto 0)));
507 if rem32(31) = '0' then
508 behave_rt := x"00000000" & rem32;
509 else
510 behave_rt := x"ffffffff" & rem32;
511 end if;
512 end if;
513 assert behave_rt = d2.write_reg_data
514 report "bad modsw expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data);
515 end loop;
516 end loop;
517 end loop;
518
519 -- test moduw
520 report "test moduw";
521 moduw_loop : for dlength in 1 to 4 loop
522 for vlength in 1 to dlength loop
523 for i in 0 to 100 loop
524 ra := std_ulogic_vector(resize(unsigned(pseudorand(dlength * 8)), 64));
525 rb := std_ulogic_vector(resize(unsigned(pseudorand(vlength * 8)), 64));
526
527 d1.dividend <= ra;
528 d1.divisor <= rb;
529 d1.is_signed <= '0';
530 d1.neg_result <= '0';
531 d1.is_extended <= '0';
532 d1.is_32bit <= '1';
533 d1.is_modulus <= '1';
534 d1.valid <= '1';
535
536 wait for clk_period;
537
538 d1.valid <= '0';
539 for j in 0 to 66 loop
540 wait for clk_period;
541 if d2.valid = '1' then
542 exit;
543 end if;
544 end loop;
545 assert d2.valid = '1';
546
547 behave_rt := (others => '0');
548 if rb /= x"0000000000000000" then
549 behave_rt := x"00000000" & std_ulogic_vector(unsigned(ra(31 downto 0)) rem unsigned(rb(31 downto 0)));
550 end if;
551 assert behave_rt(31 downto 0) = d2.write_reg_data(31 downto 0)
552 report "bad moduw expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data);
553 end loop;
554 end loop;
555 end loop;
556
557 assert false report "end of test" severity failure;
558 wait;
559 end process;
560 end behave;