library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; use work.gen_pkg.all; entity post_alu_tb is end entity post_alu_tb; architecture sim of post_alu_tb is -- TODO: braucht man hier wirklich eine andere entity definition? component alu is port ( sys_clk : in std_logic; sys_res_n : in std_logic; opcode : in alu_ops; op1 : in std_logic_vector(31 downto 0); op2 : in std_logic_vector(31 downto 0); op3 : out std_logic_vector(31 downto 0); opM : out std_logic_vector(31 downto 0); do_calc : in std_logic; calc_done : out std_logic; calc_error : out std_logic ); end component alu; signal sys_clk, sys_res_n, do_calc, calc_done, calc_error : std_logic; signal opcode : alu_ops; signal op1, op2, op3, opM : std_logic_vector((CBITS-1) downto 0); signal stop : boolean := false; begin inst : alu port map ( sys_clk => sys_clk, sys_res_n => sys_res_n, do_calc => do_calc, calc_done => calc_done, op1 => op1, op2 => op2, op3 => op3, opM => opM, opcode => opcode, calc_error => calc_error ); process begin sys_clk <= '0'; wait for 15 ns; sys_clk <= '1'; wait for 15 ns; if stop = true then wait; end if; end process; process type alu_testv is record o1 : cinteger; o : alu_ops; o2 : cinteger; om : cinteger; expected : cinteger; errcase : boolean; end record alu_testv; -- ggf. groesse des arrays erhoehen type alu_testv_array is array (natural range 0 to 65) of alu_testv; variable testmatrix : alu_testv_array := ( 0 => (-5, ALU_DIV, 3, 2, -1, false), 1 => (7, ALU_ADD, 3, 0, 10, false), 2 => (7, ALU_SUB, 1, 0, 6, false), 3 => (7, ALU_DIV, 1, 0, 7, false), 4 => (7, ALU_DIV, 3, 1, 2, false), 5 => (7, ALU_ADD, 1, 0, 8, false), 6 => (7, ALU_MUL, 3, 0, 21, false), 7 => (-7, ALU_MUL, 3, 0, -21, false), 8 => (268435456, ALU_MUL, -2, 0, -536870912, false), 9 => (268435456, ALU_MUL, 2**5, 0, 0, false), -- um fuenf nach links shiften 10 => (268435456 + 5, ALU_MUL, 2**5, 0, 160, false), -- = 5 * (2^5) 11 => (100, ALU_DIV, 10, 0, 10, false), 12 => (100, ALU_DIV, 51, 49, 1, false), 13 => (100, ALU_DIV, 49, 2, 2, false), 14 => (153156, ALU_DIV, 3543, 807, 43, false), 15 => (-153156, ALU_DIV, 3543, 807, -43, false), 16 => (153156, ALU_DIV, -3543, 807, -43, false), 17 => (-153156, ALU_DIV, -3543, 807, 43, false), -- add: sign and under-/overflow check 18 => (2147483647, ALU_ADD, -1, 0, 2147483646, false), 19 => (2147483647, ALU_ADD, 1, 0, 0, true), 20 => (-2147483645, ALU_ADD, -100, 0, 0, true), 21 => (7, ALU_ADD, 1, 0, 8, false), 22 => (7, ALU_ADD, -1, 0, 6, false), 23 => (-7, ALU_ADD, 1, 0, -6, false), 24 => (-7, ALU_ADD, -1, 0, -8, false), -- sub: sign and under-/overflow check 25 => (-7, ALU_SUB, 1, 0, -8, false), 26 => (-7, ALU_SUB, -1, 0, -6, false), 27 => (7, ALU_SUB, 1, 0, 6, false), 28 => (7, ALU_SUB, -1, 0, 8, false), 29 => (-2147483645, ALU_SUB, 1000, 0, 0, true), 30 => (2147483645, ALU_SUB, -1000, 0, 0, true), 31 => (-1000, ALU_SUB, 2147483645, 0, 0, true), 32 => (1000, ALU_SUB, -2147483645, 0, 0, true), -- mul: sign and under-/overflow check 33 => (3, ALU_MUL, 2, 0, 6, false), 34 => (3, ALU_MUL, -2, 0, -6, false), 35 => (-3, ALU_MUL, 2, 0, -6, false), 36 => (-3, ALU_MUL, -2, 0, 6, false), 37 => (90000, ALU_MUL, 100000, 0, 0, true), 38 => (90000, ALU_MUL, -100000, 0, 0, true), 39 => (-90000, ALU_MUL, 100000, 0, 0, true), 40 => (-90000, ALU_MUL, -100000, 0, 0, true), -- div: overflow check und division durch null 41 => (-2147483648, ALU_DIV, -1, 0, 0, true), 42 => (-2147483648, ALU_DIV, 0, 0, 0, true), 43 => (-4, ALU_DIV, 2, 0, -2, false), -- div/mod: 44 => (1234, ALU_DIV, 3, 1, 411, false), 45 => (1, ALU_DIV, 10, 1, 0, false), 46 => (2, ALU_DIV, 10, 2, 0, false), 47 => (3, ALU_DIV, 10, 3, 0, false), 48 => (4, ALU_DIV, 10, 4, 0, false), 49 => (5, ALU_DIV, 10, 5, 0, false), 50 => (6, ALU_DIV, 10, 6, 0, false), 51 => (7, ALU_DIV, 10, 7, 0, false), 52 => (8, ALU_DIV, 10, 8, 0, false), 53 => (9, ALU_DIV, 10, 9, 0, false), 54 => (0, ALU_DIV, 10, 0, 0, false), 55 => (10, ALU_DIV, 10, 0, 1, false), 56 => (5134123, ALU_DIV, 358015, 121913, 14, false), -- extra 60 => (5, ALU_SUB, -2147483648, 0, 0, true), 61 => (-2147483647, ALU_SUB, 1, 0, -2147483648, false), 62 => (-2147483647, ALU_ADD, -1, 0, -2147483648, false), 63 => (-2147483648, ALU_DIV, 10, 8, -214748364, false), 64 => (-214748364, ALU_DIV, 10, 4, -21474836, false), 65 => (1, ALU_DIV, -2147483648, 1, 0, false), others => (0, ALU_ADD, 0, 0, 0, false) ); variable checkall : boolean := true; begin -- init & reset sys_res_n <= '0'; do_calc <= '0'; opcode <= ALU_NOP; op1 <= (others => '0'); op2 <= (others => '0'); icwait(sys_clk, 30); sys_res_n <= '1'; for i in testmatrix'range loop icwait(sys_clk, 10); op1 <= std_logic_vector(to_signed(testmatrix(i).o1,CBITS)); opcode <= testmatrix(i).o; op2 <= std_logic_vector(to_signed(testmatrix(i).o2,CBITS)); -- berechnung kann los gehen do_calc <= '1'; -- warten auf die alu einheit wait on calc_done; icwait(sys_clk, 1); if testmatrix(i).errcase then if (calc_error = '0') then assert(false) report "sollte ein error sein"; assert op3 = std_logic_vector(to_signed(testmatrix(i).expected,CBITS)) report "" & cinteger'image(testmatrix(i).o1) & " " & integer'image(to_integer(signed(opcode))) & " " & cinteger'image(testmatrix(i).o2) & "/= " & integer'image(to_integer(signed(op3))) & " -- erwartet: " & cinteger'image(testmatrix(i).expected); checkall := false; else assert(false) report "testfall war ein error (passt)"; end if; else if not((op3 = std_logic_vector(to_signed(testmatrix(i).expected,CBITS))) and (opcode /= ALU_DIV or opM = std_logic_vector(to_signed(testmatrix(i).om,CBITS)))) then assert(false) report "" & cinteger'image(testmatrix(i).o1) & " " & integer'image(to_integer(signed(opcode))) & " " & cinteger'image(testmatrix(i).o2) & "/= " & integer'image(to_integer(signed(op3))) & " -- erwartet: " & cinteger'image(testmatrix(i).expected); checkall := false; end if; end if; icwait(sys_clk, 2); -- ack it! do_calc <= '0'; end loop; if checkall then report "alle testfaelle der ALU waren erfolgreich!"; else report "einige testfaelle schlugen fehl"; end if; stop <= true; wait; end process; end architecture sim;