Merge pull request #74 from paulusmack/divider
[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 : Decode2ToDividerType;
20 signal d2 : DividerToWritebackType;
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 begin
39 rst <= '1';
40 wait for clk_period;
41 rst <= '0';
42
43 d1.valid <= '1';
44 d1.write_reg <= "10001";
45 d1.dividend <= x"0000000010001000";
46 d1.divisor <= x"0000000000001111";
47 d1.is_signed <= '0';
48 d1.is_32bit <= '0';
49 d1.is_extended <= '0';
50 d1.is_modulus <= '0';
51 d1.rc <= '0';
52
53 wait for clk_period;
54 assert d2.valid = '0';
55
56 d1.valid <= '0';
57
58 for j in 0 to 65 loop
59 wait for clk_period;
60 if d2.valid = '1' then
61 exit;
62 end if;
63 end loop;
64
65 assert d2.valid = '1';
66 assert d2.write_reg_enable = '1';
67 assert d2.write_reg_nr = "10001";
68 assert d2.write_reg_data = x"000000000000f001" report "result " & to_hstring(d2.write_reg_data);
69 assert d2.write_cr_enable = '0';
70
71 wait for clk_period;
72 assert d2.valid = '0' report "valid";
73
74 d1.valid <= '1';
75 d1.rc <= '1';
76
77 wait for clk_period;
78 assert d2.valid = '0' report "valid";
79
80 d1.valid <= '0';
81
82 for j in 0 to 65 loop
83 wait for clk_period;
84 if d2.valid = '1' then
85 exit;
86 end if;
87 end loop;
88
89 assert d2.valid = '1';
90 assert d2.write_reg_enable = '1';
91 assert d2.write_reg_nr = "10001";
92 assert d2.write_reg_data = x"000000000000f001" report "result " & to_hstring(d2.write_reg_data);
93 assert d2.write_cr_enable = '1';
94 assert d2.write_cr_mask = "10000000";
95 assert d2.write_cr_data = x"40000000" report "cr data is " & to_hstring(d2.write_cr_data);
96
97 wait for clk_period;
98 assert d2.valid = '0';
99
100 -- test divd
101 report "test divd";
102 divd_loop : for dlength in 1 to 8 loop
103 for vlength in 1 to dlength loop
104 for i in 0 to 100 loop
105 ra := std_ulogic_vector(resize(signed(pseudorand(dlength * 8)), 64));
106 rb := std_ulogic_vector(resize(signed(pseudorand(vlength * 8)), 64));
107
108 d1.dividend <= ra;
109 d1.divisor <= rb;
110 d1.is_signed <= '1';
111 d1.valid <= '1';
112
113 wait for clk_period;
114
115 d1.valid <= '0';
116 for j in 0 to 65 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 if rb /= x"0000000000000000" then
125 behave_rt := ppc_divd(ra, rb);
126 assert to_hstring(behave_rt) = to_hstring(d2.write_reg_data)
127 report "bad divd expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data);
128 assert ppc_cmpi('1', behave_rt, x"0000") & x"0000000" = d2.write_cr_data
129 report "bad CR setting for divd";
130 end if;
131 end loop;
132 end loop;
133 end loop;
134
135 -- test divdu
136 report "test divdu";
137 divdu_loop : for dlength in 1 to 8 loop
138 for vlength in 1 to dlength loop
139 for i in 0 to 100 loop
140 ra := std_ulogic_vector(resize(unsigned(pseudorand(dlength * 8)), 64));
141 rb := std_ulogic_vector(resize(unsigned(pseudorand(vlength * 8)), 64));
142
143 d1.dividend <= ra;
144 d1.divisor <= rb;
145 d1.is_signed <= '0';
146 d1.valid <= '1';
147
148 wait for clk_period;
149
150 d1.valid <= '0';
151 for j in 0 to 65 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 if rb /= x"0000000000000000" then
160 behave_rt := ppc_divdu(ra, rb);
161 assert to_hstring(behave_rt) = to_hstring(d2.write_reg_data)
162 report "bad divdu expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data);
163 assert ppc_cmpi('1', behave_rt, x"0000") & x"0000000" = d2.write_cr_data
164 report "bad CR setting for divdu";
165 end if;
166 end loop;
167 end loop;
168 end loop;
169
170 -- test divde
171 report "test divde";
172 divde_loop : for vlength in 1 to 8 loop
173 for dlength in 1 to vlength loop
174 for i in 0 to 100 loop
175 ra := std_ulogic_vector(resize(signed(pseudorand(dlength * 8)), 64));
176 rb := std_ulogic_vector(resize(signed(pseudorand(vlength * 8)), 64));
177
178 d1.dividend <= ra;
179 d1.divisor <= rb;
180 d1.is_signed <= '1';
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 65 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 if rb /= x"0000000000000000" then
196 d128 := ra & x"0000000000000000";
197 q128 := std_ulogic_vector(signed(d128) / signed(rb));
198 if q128(127 downto 63) = x"0000000000000000" & '0' or
199 q128(127 downto 63) = x"ffffffffffffffff" & '1' then
200 behave_rt := q128(63 downto 0);
201 assert to_hstring(behave_rt) = to_hstring(d2.write_reg_data)
202 report "bad divde expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data) & " for ra = " & to_hstring(ra) & " rb = " & to_hstring(rb);
203 assert ppc_cmpi('1', behave_rt, x"0000") & x"0000000" = d2.write_cr_data
204 report "bad CR setting for divde";
205 end if;
206 end if;
207 end loop;
208 end loop;
209 end loop;
210
211 -- test divdeu
212 report "test divdeu";
213 divdeu_loop : for vlength in 1 to 8 loop
214 for dlength in 1 to vlength loop
215 for i in 0 to 100 loop
216 ra := std_ulogic_vector(resize(unsigned(pseudorand(dlength * 8)), 64));
217 rb := std_ulogic_vector(resize(unsigned(pseudorand(vlength * 8)), 64));
218
219 d1.dividend <= ra;
220 d1.divisor <= rb;
221 d1.is_signed <= '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 65 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 if unsigned(rb) > unsigned(ra) then
237 d128 := ra & x"0000000000000000";
238 q128 := std_ulogic_vector(unsigned(d128) / unsigned(rb));
239 behave_rt := q128(63 downto 0);
240 assert to_hstring(behave_rt) = to_hstring(d2.write_reg_data)
241 report "bad divdeu expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data) & " for ra = " & to_hstring(ra) & " rb = " & to_hstring(rb);
242 assert ppc_cmpi('1', behave_rt, x"0000") & x"0000000" = d2.write_cr_data
243 report "bad CR setting for divdeu";
244 end if;
245 end loop;
246 end loop;
247 end loop;
248
249 -- test divw
250 report "test divw";
251 divw_loop : for dlength in 1 to 4 loop
252 for vlength in 1 to dlength loop
253 for i in 0 to 100 loop
254 ra := std_ulogic_vector(resize(signed(pseudorand(dlength * 8)), 64));
255 rb := std_ulogic_vector(resize(signed(pseudorand(vlength * 8)), 64));
256
257 d1.dividend <= ra;
258 d1.divisor <= rb;
259 d1.is_signed <= '1';
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 65 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 if rb /= x"0000000000000000" then
276 behave_rt := ppc_divw(ra, rb);
277 assert behave_rt(31 downto 0) = d2.write_reg_data(31 downto 0)
278 report "bad divw expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data);
279 assert ppc_cmpi('0', behave_rt, x"0000") & x"0000000" = d2.write_cr_data
280 report "bad CR setting for divw";
281 end if;
282 end loop;
283 end loop;
284 end loop;
285
286 -- test divwu
287 report "test divwu";
288 divwu_loop : for dlength in 1 to 4 loop
289 for vlength in 1 to dlength loop
290 for i in 0 to 100 loop
291 ra := std_ulogic_vector(resize(unsigned(pseudorand(dlength * 8)), 64));
292 rb := std_ulogic_vector(resize(unsigned(pseudorand(vlength * 8)), 64));
293
294 d1.dividend <= ra;
295 d1.divisor <= rb;
296 d1.is_signed <= '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 65 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 if rb /= x"0000000000000000" then
313 behave_rt := ppc_divwu(ra, rb);
314 assert behave_rt(31 downto 0) = d2.write_reg_data(31 downto 0)
315 report "bad divwu expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data);
316 assert ppc_cmpi('0', behave_rt, x"0000") & x"0000000" = d2.write_cr_data
317 report "bad CR setting for divwu";
318 end if;
319 end loop;
320 end loop;
321 end loop;
322
323 -- test divwe
324 report "test divwe";
325 divwe_loop : for vlength in 1 to 4 loop
326 for dlength in 1 to vlength loop
327 for i in 0 to 100 loop
328 ra := std_ulogic_vector(resize(signed(pseudorand(dlength * 8)), 32)) & x"00000000";
329 rb := std_ulogic_vector(resize(signed(pseudorand(vlength * 8)), 64));
330
331 d1.dividend <= ra;
332 d1.divisor <= rb;
333 d1.is_signed <= '1';
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 65 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 if rb /= x"0000000000000000" then
350 behave_rt := std_ulogic_vector(signed(ra) / signed(rb));
351 if behave_rt(63 downto 31) = x"00000000" & '0' or
352 behave_rt(63 downto 31) = x"ffffffff" & '1' then
353 assert behave_rt(31 downto 0) = d2.write_reg_data(31 downto 0)
354 report "bad divwe expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data) & " for ra = " & to_hstring(ra) & " rb = " & to_hstring(rb);
355 assert ppc_cmpi('0', behave_rt, x"0000") & x"0000000" = d2.write_cr_data
356 report "bad CR setting for divwe";
357 end if;
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.is_extended <= '0';
375 d1.is_32bit <= '1';
376 d1.valid <= '1';
377
378 wait for clk_period;
379
380 d1.valid <= '0';
381 for j in 0 to 65 loop
382 wait for clk_period;
383 if d2.valid = '1' then
384 exit;
385 end if;
386 end loop;
387 assert d2.valid = '1';
388
389 if unsigned(rb(31 downto 0)) > unsigned(ra(63 downto 32)) then
390 behave_rt := std_ulogic_vector(unsigned(ra) / unsigned(rb));
391 assert behave_rt(31 downto 0) = d2.write_reg_data(31 downto 0)
392 report "bad divweu expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data) & " for ra = " & to_hstring(ra) & " rb = " & to_hstring(rb);
393 assert ppc_cmpi('0', behave_rt, x"0000") & x"0000000" = d2.write_cr_data
394 report "bad CR setting for divweu";
395 end if;
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;
409 d1.divisor <= rb;
410 d1.is_signed <= '1';
411 d1.is_extended <= '0';
412 d1.is_32bit <= '0';
413 d1.is_modulus <= '1';
414 d1.valid <= '1';
415
416 wait for clk_period;
417
418 d1.valid <= '0';
419 for j in 0 to 65 loop
420 wait for clk_period;
421 if d2.valid = '1' then
422 exit;
423 end if;
424 end loop;
425 assert d2.valid = '1';
426
427 if rb /= x"0000000000000000" then
428 behave_rt := std_ulogic_vector(signed(ra) rem signed(rb));
429 assert behave_rt = d2.write_reg_data
430 report "bad modsd expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data);
431 assert ppc_cmpi('1', behave_rt, x"0000") & x"0000000" = d2.write_cr_data
432 report "bad CR setting for modsd";
433 end if;
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.is_extended <= '0';
450 d1.is_32bit <= '0';
451 d1.is_modulus <= '1';
452 d1.valid <= '1';
453
454 wait for clk_period;
455
456 d1.valid <= '0';
457 for j in 0 to 65 loop
458 wait for clk_period;
459 if d2.valid = '1' then
460 exit;
461 end if;
462 end loop;
463 assert d2.valid = '1';
464
465 if rb /= x"0000000000000000" then
466 behave_rt := std_ulogic_vector(unsigned(ra) rem unsigned(rb));
467 assert behave_rt = d2.write_reg_data
468 report "bad modud expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data);
469 assert ppc_cmpi('1', behave_rt, x"0000") & x"0000000" = d2.write_cr_data
470 report "bad CR setting for modud";
471 end if;
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;
485 d1.divisor <= rb;
486 d1.is_signed <= '1';
487 d1.is_extended <= '0';
488 d1.is_32bit <= '1';
489 d1.is_modulus <= '1';
490 d1.valid <= '1';
491
492 wait for clk_period;
493
494 d1.valid <= '0';
495 for j in 0 to 65 loop
496 wait for clk_period;
497 if d2.valid = '1' then
498 exit;
499 end if;
500 end loop;
501 assert d2.valid = '1';
502
503 if rb /= x"0000000000000000" then
504 behave_rt := x"00000000" & std_ulogic_vector(signed(ra(31 downto 0)) rem signed(rb(31 downto 0)));
505 assert behave_rt(31 downto 0) = d2.write_reg_data(31 downto 0)
506 report "bad modsw expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data);
507 assert ppc_cmpi('0', behave_rt, x"0000") & x"0000000" = d2.write_cr_data
508 report "bad CR setting for modsw";
509 end if;
510 end loop;
511 end loop;
512 end loop;
513
514 -- test moduw
515 report "test moduw";
516 moduw_loop : for dlength in 1 to 4 loop
517 for vlength in 1 to dlength loop
518 for i in 0 to 100 loop
519 ra := std_ulogic_vector(resize(unsigned(pseudorand(dlength * 8)), 64));
520 rb := std_ulogic_vector(resize(unsigned(pseudorand(vlength * 8)), 64));
521
522 d1.dividend <= ra;
523 d1.divisor <= rb;
524 d1.is_signed <= '0';
525 d1.is_extended <= '0';
526 d1.is_32bit <= '1';
527 d1.is_modulus <= '1';
528 d1.valid <= '1';
529
530 wait for clk_period;
531
532 d1.valid <= '0';
533 for j in 0 to 65 loop
534 wait for clk_period;
535 if d2.valid = '1' then
536 exit;
537 end if;
538 end loop;
539 assert d2.valid = '1';
540
541 if rb /= x"0000000000000000" then
542 behave_rt := x"00000000" & std_ulogic_vector(unsigned(ra(31 downto 0)) rem unsigned(rb(31 downto 0)));
543 assert behave_rt(31 downto 0) = d2.write_reg_data(31 downto 0)
544 report "bad moduw expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data);
545 assert ppc_cmpi('0', behave_rt, x"0000") & x"0000000" = d2.write_cr_data
546 report "bad CR setting for moduw";
547 end if;
548 end loop;
549 end loop;
550 end loop;
551
552 assert false report "end of test" severity failure;
553 wait;
554 end process;
555 end behave;