Merge pull request #144 from antonblanchard/update-README
[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 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.rc <= '0';
54
55 wait for clk_period;
56 assert d2.valid = '0';
57
58 d1.valid <= '0';
59
60 for j in 0 to 66 loop
61 wait for clk_period;
62 if d2.valid = '1' then
63 exit;
64 end if;
65 end loop;
66
67 assert d2.valid = '1';
68 assert d2.write_reg_enable = '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_enable = '1';
93 assert d2.write_reg_nr = "10001";
94 assert d2.write_reg_data = x"000000000000f001" report "result " & to_hstring(d2.write_reg_data);
95 assert d2.rc = '1';
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 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.valid <= '1';
146
147 wait for clk_period;
148
149 d1.valid <= '0';
150 for j in 0 to 66 loop
151 wait for clk_period;
152 if d2.valid = '1' then
153 exit;
154 end if;
155 end loop;
156 assert d2.valid = '1';
157
158 behave_rt := (others => '0');
159 if rb /= x"0000000000000000" then
160 behave_rt := ppc_divdu(ra, rb);
161 end if;
162 assert to_hstring(behave_rt) = to_hstring(d2.write_reg_data)
163 report "bad divdu expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data);
164 end loop;
165 end loop;
166 end loop;
167
168 -- test divde
169 report "test divde";
170 divde_loop : for vlength in 1 to 8 loop
171 for dlength in 1 to vlength loop
172 for i in 0 to 100 loop
173 ra := std_ulogic_vector(resize(signed(pseudorand(dlength * 8)), 64));
174 rb := std_ulogic_vector(resize(signed(pseudorand(vlength * 8)), 64));
175
176 d1.dividend <= ra;
177 d1.divisor <= rb;
178 d1.is_signed <= '1';
179 d1.is_extended <= '1';
180 d1.valid <= '1';
181
182 wait for clk_period;
183
184 d1.valid <= '0';
185 for j in 0 to 66 loop
186 wait for clk_period;
187 if d2.valid = '1' then
188 exit;
189 end if;
190 end loop;
191 assert d2.valid = '1';
192
193 behave_rt := (others => '0');
194 if rb /= x"0000000000000000" then
195 d128 := ra & x"0000000000000000";
196 q128 := std_ulogic_vector(signed(d128) / signed(rb));
197 if q128(127 downto 63) = x"0000000000000000" & '0' or
198 q128(127 downto 63) = x"ffffffffffffffff" & '1' then
199 behave_rt := q128(63 downto 0);
200 end if;
201 end if;
202 assert to_hstring(behave_rt) = to_hstring(d2.write_reg_data)
203 report "bad divde expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data) & " for ra = " & to_hstring(ra) & " rb = " & to_hstring(rb);
204 end loop;
205 end loop;
206 end loop;
207
208 -- test divdeu
209 report "test divdeu";
210 divdeu_loop : for vlength in 1 to 8 loop
211 for dlength in 1 to vlength loop
212 for i in 0 to 100 loop
213 ra := std_ulogic_vector(resize(unsigned(pseudorand(dlength * 8)), 64));
214 rb := std_ulogic_vector(resize(unsigned(pseudorand(vlength * 8)), 64));
215
216 d1.dividend <= ra;
217 d1.divisor <= rb;
218 d1.is_signed <= '0';
219 d1.is_extended <= '1';
220 d1.valid <= '1';
221
222 wait for clk_period;
223
224 d1.valid <= '0';
225 for j in 0 to 66 loop
226 wait for clk_period;
227 if d2.valid = '1' then
228 exit;
229 end if;
230 end loop;
231 assert d2.valid = '1';
232
233 behave_rt := (others => '0');
234 if unsigned(rb) > unsigned(ra) then
235 d128 := ra & x"0000000000000000";
236 q128 := std_ulogic_vector(unsigned(d128) / unsigned(rb));
237 behave_rt := q128(63 downto 0);
238 end if;
239 assert to_hstring(behave_rt) = to_hstring(d2.write_reg_data)
240 report "bad divdeu expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data) & " for ra = " & to_hstring(ra) & " rb = " & to_hstring(rb);
241 end loop;
242 end loop;
243 end loop;
244
245 -- test divw
246 report "test divw";
247 divw_loop : for dlength in 1 to 4 loop
248 for vlength in 1 to dlength loop
249 for i in 0 to 100 loop
250 ra := std_ulogic_vector(resize(signed(pseudorand(dlength * 8)), 64));
251 rb := std_ulogic_vector(resize(signed(pseudorand(vlength * 8)), 64));
252
253 d1.dividend <= ra;
254 d1.divisor <= rb;
255 d1.is_signed <= '1';
256 d1.is_extended <= '0';
257 d1.is_32bit <= '1';
258 d1.valid <= '1';
259
260 wait for clk_period;
261
262 d1.valid <= '0';
263 for j in 0 to 66 loop
264 wait for clk_period;
265 if d2.valid = '1' then
266 exit;
267 end if;
268 end loop;
269 assert d2.valid = '1';
270
271 behave_rt := (others => '0');
272 if rb /= x"0000000000000000" and (ra /= x"ffffffff80000000" or rb /= x"ffffffffffffffff") then
273 behave_rt := ppc_divw(ra, rb);
274 end if;
275 assert behave_rt = d2.write_reg_data
276 report "bad divw expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data);
277 end loop;
278 end loop;
279 end loop;
280
281 -- test divwu
282 report "test divwu";
283 divwu_loop : for dlength in 1 to 4 loop
284 for vlength in 1 to dlength loop
285 for i in 0 to 100 loop
286 ra := std_ulogic_vector(resize(unsigned(pseudorand(dlength * 8)), 64));
287 rb := std_ulogic_vector(resize(unsigned(pseudorand(vlength * 8)), 64));
288
289 d1.dividend <= ra;
290 d1.divisor <= rb;
291 d1.is_signed <= '0';
292 d1.is_extended <= '0';
293 d1.is_32bit <= '1';
294 d1.valid <= '1';
295
296 wait for clk_period;
297
298 d1.valid <= '0';
299 for j in 0 to 66 loop
300 wait for clk_period;
301 if d2.valid = '1' then
302 exit;
303 end if;
304 end loop;
305 assert d2.valid = '1';
306
307 behave_rt := (others => '0');
308 if rb /= x"0000000000000000" then
309 behave_rt := ppc_divwu(ra, rb);
310 end if;
311 assert behave_rt = d2.write_reg_data
312 report "bad divwu expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data);
313 end loop;
314 end loop;
315 end loop;
316
317 -- test divwe
318 report "test divwe";
319 divwe_loop : for vlength in 1 to 4 loop
320 for dlength in 1 to vlength loop
321 for i in 0 to 100 loop
322 ra := std_ulogic_vector(resize(signed(pseudorand(dlength * 8)), 32)) & x"00000000";
323 rb := std_ulogic_vector(resize(signed(pseudorand(vlength * 8)), 64));
324
325 d1.dividend <= ra;
326 d1.divisor <= rb;
327 d1.is_signed <= '1';
328 d1.is_extended <= '0';
329 d1.is_32bit <= '1';
330 d1.valid <= '1';
331
332 wait for clk_period;
333
334 d1.valid <= '0';
335 for j in 0 to 66 loop
336 wait for clk_period;
337 if d2.valid = '1' then
338 exit;
339 end if;
340 end loop;
341 assert d2.valid = '1';
342
343 behave_rt := (others => '0');
344 if rb /= x"0000000000000000" then
345 q64 := std_ulogic_vector(signed(ra) / signed(rb));
346 if q64(63 downto 31) = x"00000000" & '0' or
347 q64(63 downto 31) = x"ffffffff" & '1' then
348 behave_rt := x"00000000" & q64(31 downto 0);
349 end if;
350 assert behave_rt = d2.write_reg_data
351 report "bad divwe expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data) & " for ra = " & to_hstring(ra) & " rb = " & to_hstring(rb);
352 end if;
353 end loop;
354 end loop;
355 end loop;
356
357 -- test divweu
358 report "test divweu";
359 divweu_loop : for vlength in 1 to 4 loop
360 for dlength in 1 to vlength loop
361 for i in 0 to 100 loop
362 ra := std_ulogic_vector(resize(unsigned(pseudorand(dlength * 8)), 32)) & x"00000000";
363 rb := std_ulogic_vector(resize(unsigned(pseudorand(vlength * 8)), 64));
364
365 d1.dividend <= ra;
366 d1.divisor <= rb;
367 d1.is_signed <= '0';
368 d1.is_extended <= '0';
369 d1.is_32bit <= '1';
370 d1.valid <= '1';
371
372 wait for clk_period;
373
374 d1.valid <= '0';
375 for j in 0 to 66 loop
376 wait for clk_period;
377 if d2.valid = '1' then
378 exit;
379 end if;
380 end loop;
381 assert d2.valid = '1';
382
383 behave_rt := (others => '0');
384 if unsigned(rb(31 downto 0)) > unsigned(ra(63 downto 32)) then
385 behave_rt := std_ulogic_vector(unsigned(ra) / unsigned(rb));
386 end if;
387 assert behave_rt = d2.write_reg_data
388 report "bad divweu expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data) & " for ra = " & to_hstring(ra) & " rb = " & to_hstring(rb);
389 end loop;
390 end loop;
391 end loop;
392
393 -- test modsd
394 report "test modsd";
395 modsd_loop : for dlength in 1 to 8 loop
396 for vlength in 1 to dlength loop
397 for i in 0 to 100 loop
398 ra := std_ulogic_vector(resize(signed(pseudorand(dlength * 8)), 64));
399 rb := std_ulogic_vector(resize(signed(pseudorand(vlength * 8)), 64));
400
401 d1.dividend <= ra;
402 d1.divisor <= rb;
403 d1.is_signed <= '1';
404 d1.is_extended <= '0';
405 d1.is_32bit <= '0';
406 d1.is_modulus <= '1';
407 d1.valid <= '1';
408
409 wait for clk_period;
410
411 d1.valid <= '0';
412 for j in 0 to 66 loop
413 wait for clk_period;
414 if d2.valid = '1' then
415 exit;
416 end if;
417 end loop;
418 assert d2.valid = '1';
419
420 behave_rt := (others => '0');
421 if rb /= x"0000000000000000" then
422 behave_rt := std_ulogic_vector(signed(ra) rem signed(rb));
423 end if;
424 assert behave_rt = d2.write_reg_data
425 report "bad modsd expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data);
426 end loop;
427 end loop;
428 end loop;
429
430 -- test modud
431 report "test modud";
432 modud_loop : for dlength in 1 to 8 loop
433 for vlength in 1 to dlength loop
434 for i in 0 to 100 loop
435 ra := std_ulogic_vector(resize(unsigned(pseudorand(dlength * 8)), 64));
436 rb := std_ulogic_vector(resize(unsigned(pseudorand(vlength * 8)), 64));
437
438 d1.dividend <= ra;
439 d1.divisor <= rb;
440 d1.is_signed <= '0';
441 d1.is_extended <= '0';
442 d1.is_32bit <= '0';
443 d1.is_modulus <= '1';
444 d1.valid <= '1';
445
446 wait for clk_period;
447
448 d1.valid <= '0';
449 for j in 0 to 66 loop
450 wait for clk_period;
451 if d2.valid = '1' then
452 exit;
453 end if;
454 end loop;
455 assert d2.valid = '1';
456
457 behave_rt := (others => '0');
458 if rb /= x"0000000000000000" then
459 behave_rt := std_ulogic_vector(unsigned(ra) rem unsigned(rb));
460 end if;
461 assert behave_rt = d2.write_reg_data
462 report "bad modud expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data);
463 end loop;
464 end loop;
465 end loop;
466
467 -- test modsw
468 report "test modsw";
469 modsw_loop : for dlength in 1 to 4 loop
470 for vlength in 1 to dlength loop
471 for i in 0 to 100 loop
472 ra := std_ulogic_vector(resize(signed(pseudorand(dlength * 8)), 64));
473 rb := std_ulogic_vector(resize(signed(pseudorand(vlength * 8)), 64));
474
475 d1.dividend <= ra;
476 d1.divisor <= rb;
477 d1.is_signed <= '1';
478 d1.is_extended <= '0';
479 d1.is_32bit <= '1';
480 d1.is_modulus <= '1';
481 d1.valid <= '1';
482
483 wait for clk_period;
484
485 d1.valid <= '0';
486 for j in 0 to 66 loop
487 wait for clk_period;
488 if d2.valid = '1' then
489 exit;
490 end if;
491 end loop;
492 assert d2.valid = '1';
493
494 behave_rt := (others => '0');
495 if rb /= x"0000000000000000" then
496 rem32 := std_ulogic_vector(signed(ra(31 downto 0)) rem signed(rb(31 downto 0)));
497 if rem32(31) = '0' then
498 behave_rt := x"00000000" & rem32;
499 else
500 behave_rt := x"ffffffff" & rem32;
501 end if;
502 end if;
503 assert behave_rt = d2.write_reg_data
504 report "bad modsw expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data);
505 end loop;
506 end loop;
507 end loop;
508
509 -- test moduw
510 report "test moduw";
511 moduw_loop : for dlength in 1 to 4 loop
512 for vlength in 1 to dlength loop
513 for i in 0 to 100 loop
514 ra := std_ulogic_vector(resize(unsigned(pseudorand(dlength * 8)), 64));
515 rb := std_ulogic_vector(resize(unsigned(pseudorand(vlength * 8)), 64));
516
517 d1.dividend <= ra;
518 d1.divisor <= rb;
519 d1.is_signed <= '0';
520 d1.is_extended <= '0';
521 d1.is_32bit <= '1';
522 d1.is_modulus <= '1';
523 d1.valid <= '1';
524
525 wait for clk_period;
526
527 d1.valid <= '0';
528 for j in 0 to 66 loop
529 wait for clk_period;
530 if d2.valid = '1' then
531 exit;
532 end if;
533 end loop;
534 assert d2.valid = '1';
535
536 behave_rt := (others => '0');
537 if rb /= x"0000000000000000" then
538 behave_rt := x"00000000" & std_ulogic_vector(unsigned(ra(31 downto 0)) rem unsigned(rb(31 downto 0)));
539 end if;
540 assert behave_rt(31 downto 0) = d2.write_reg_data(31 downto 0)
541 report "bad moduw expected " & to_hstring(behave_rt) & " got " & to_hstring(d2.write_reg_data);
542 end loop;
543 end loop;
544 end loop;
545
546 assert false report "end of test" severity failure;
547 wait;
548 end process;
549 end behave;