alu: error flag setzen bei overflow/underflow bzw. bei division durch 0
[hwmod.git] / src / beh_alu_tb.vhd
1 library ieee;
2 use ieee.std_logic_1164.all;
3 use ieee.numeric_std.all;
4 use work.gen_pkg.all;
5
6 entity beh_alu_tb is
7 end entity beh_alu_tb;
8
9 architecture sim of beh_alu_tb is
10         signal sys_clk, sys_res_n, do_calc, calc_done, calc_error : std_logic;
11         signal opcode : alu_ops;
12         signal op1, op2, op3 : csigned;
13         signal stop : boolean := false;
14 begin
15         inst : entity work.alu(beh)
16         port map
17         (
18                 sys_clk => sys_clk,
19                 sys_res_n => sys_res_n,
20                 do_calc => do_calc,
21                 calc_done => calc_done,
22                 op1 => op1,
23                 op2 => op2,
24                 op3 => op3,
25                 opcode => opcode,
26                 calc_error => calc_error
27         );
28
29         process
30         begin
31                 sys_clk <= '0';
32                 wait for 15 ns;
33                 sys_clk <= '1';
34                 wait for 15 ns;
35                 if stop = true then
36                         wait;
37                 end if;
38         end process;
39
40         process
41                 type alu_testv is record
42                         o1 : cinteger;
43                         o : alu_ops;
44                         o2 : cinteger;
45                         expected : cinteger;
46                         errcase : boolean;
47                 end record alu_testv;
48
49                 -- ggf. groesse des arrays erhoehen
50                 type alu_testv_array is array (natural range 0 to 44) of alu_testv;
51
52                 variable testmatrix : alu_testv_array :=
53                         ( 0 => (-5, ALU_DIV, 3, -1, false),
54                           1 => (7, ALU_ADD, 3, 10, false),
55                           2 => (7, ALU_SUB, 1, 6, false),
56                           3 => (7, ALU_DIV, 1, 7, false),
57                           4 => (7, ALU_DIV, 3, 2, false),
58                           5 => (7, ALU_ADD, 1, 8, false),
59                           6 => (7, ALU_MUL, 3, 21, false),
60                           7 => (-7, ALU_MUL, 3, -21, false),
61                           8 => (268435456, ALU_MUL, -2, -536870912, false),
62                           9 => (268435456, ALU_MUL, 2**5, 0, false), -- um fuenf nach links shiften
63                           10 => (268435456 + 5, ALU_MUL, 2**5, 160, false), -- = 5 * (2^5)
64                           11 => (100, ALU_DIV, 10, 10, false),
65                           12 => (100, ALU_DIV, 51, 1, false),
66                           13 => (100, ALU_DIV, 49, 2, false),
67                           14 => (153156, ALU_DIV, 3543, 43, false),
68                           15 => (-153156, ALU_DIV, 3543, -43, false),
69                           16 => (153156, ALU_DIV, -3543, -43, false),
70                           17 => (-153156, ALU_DIV, -3543, 43, false),
71                           -- add: sign and under-/overflow check
72                           18 => (2147483647, ALU_ADD, -1, 2147483646, false),
73                           19 => (2147483647, ALU_ADD, 1, 0, true),
74                           20 => (-2147483645, ALU_ADD, -100, 0, true),
75                           21 => (7, ALU_ADD, 1, 8, false),
76                           22 => (7, ALU_ADD, -1, 6, false),
77                           23 => (-7, ALU_ADD, 1, -6, false),
78                           24 => (-7, ALU_ADD, -1, -8, false),
79                           -- sub: sign and under-/overflow check
80                           25 => (-7, ALU_SUB, 1, -8, false),
81                           26 => (-7, ALU_SUB, -1, -6, false),
82                           27 => (7, ALU_SUB, 1, 6, false),
83                           28 => (7, ALU_SUB, -1, 8, false),
84                           29 => (-2147483645, ALU_SUB, 1000, 0, true),
85                           30 => (2147483645, ALU_SUB, -1000, 0, true),
86                           31 => (-1000, ALU_SUB, 2147483645, 0, true),
87                           32 => (1000, ALU_SUB, -2147483645, 0, true),
88                           -- mul: sign and under-/overflow check
89                           33 => (3, ALU_MUL, 2, 6, false),
90                           34 => (3, ALU_MUL, -2, -6, false),
91                           35 => (-3, ALU_MUL, 2, -6, false),
92                           36 => (-3, ALU_MUL, -2, 6, false),
93                           37 => (90000, ALU_MUL, 100000, 0, true),
94                           38 => (90000, ALU_MUL, -100000, 0, true),
95                           39 => (-90000, ALU_MUL, 100000, 0, true),
96                           40 => (-90000, ALU_MUL, -100000, 0, true),
97                           -- mul: overflow check und division durch null
98                           41 => (-2147483648, ALU_DIV, -1, 0, true),
99                           42 => (-2147483648, ALU_DIV, 0, 0, true),
100                           others => (0, ALU_ADD, 0, 0, false)
101                         );
102                 variable checkall : boolean := true;
103         begin
104                 -- init & reset
105                 sys_res_n <= '0';
106                 do_calc <= '0';
107                 opcode <= ALU_NOP;
108                 op1 <= (others => '0');
109                 op2 <= (others => '0');
110
111                 icwait(sys_clk, 30);
112                 sys_res_n <= '1';
113
114                 for i in testmatrix'range loop
115                         icwait(sys_clk, 10);
116                         op1 <= to_signed(testmatrix(i).o1,CBITS);
117                         opcode <= testmatrix(i).o;
118                         op2 <= to_signed(testmatrix(i).o2,CBITS);
119
120                         -- berechnung kann los gehen
121                         do_calc <= '1';
122
123                         -- warten auf die alu einheit
124                         wait on calc_done;
125                         icwait(sys_clk, 1);
126
127                         if testmatrix(i).errcase then
128                                 if (calc_error = '0') then
129                                         assert(false) report "sollte ein error sein";
130                                         assert op3 = to_signed(testmatrix(i).expected,CBITS)
131                                                 report "" & cinteger'image(testmatrix(i).o1) & 
132                                                 " " & integer'image(to_integer(signed(opcode))) &
133                                                 " " & cinteger'image(testmatrix(i).o2) &
134                                                 "/= " & integer'image(to_integer(op3)) &
135                                                 " -- erwartet: " & cinteger'image(testmatrix(i).expected);
136                                         checkall := false;
137                                 else
138                                         assert(false) report "testfall war ein error (passt)";
139                                 end if;
140                         else
141                                 assert op3 = to_signed(testmatrix(i).expected,CBITS)
142                                         report "" & cinteger'image(testmatrix(i).o1) & 
143                                         " " & integer'image(to_integer(signed(opcode))) &
144                                         " " & cinteger'image(testmatrix(i).o2) &
145                                         "/= " & integer'image(to_integer(op3)) &
146                                         " -- erwartet: " & cinteger'image(testmatrix(i).expected);
147
148                                 if op3 /= to_signed(testmatrix(i).expected,CBITS) then
149                                         checkall := false;
150                                 end if;
151                         end if;
152
153                         icwait(sys_clk, 2);
154                         -- ack it!
155                         do_calc <= '0';
156                 end loop;
157
158                 if checkall then
159                         report "alle testfaelle der ALU waren erfolgreich!";
160                 else
161                         report "einige testfaelle schlugen fehl";
162                 end if;
163                 stop <= true;
164                 wait;
165         end process;
166 end architecture sim;