alu: bessere testbench
authorBernhard Urban <lewurm@gmail.com>
Sat, 10 Apr 2010 14:36:37 +0000 (16:36 +0200)
committerBernhard Urban <lewurm@gmail.com>
Sat, 10 Apr 2010 14:40:24 +0000 (16:40 +0200)
alu: interne struktur leicht veraendert. ack signal wieder entfernt (doch nicht noetig)

src/alu.do
src/alu.vhd
src/alu_tb.vhd
src/gen_pkg.vhd

index 337baffdacef0cfe694aba56d2f85310bbd7248b..98ddba09ae57c56ac8b293683004c028b15a6b0d 100644 (file)
@@ -1,20 +1,22 @@
+#alias fuer simulation neustarten
+alias rr "restart -f"
+
 #signale hinzufuegen
 add wave sys_clk
 add wave sys_res_n
-add wave opcode
 add wave op1
+add wave opcode
 add wave op2
 add wave op3
-add wave optmp
 add wave do_calc
 add wave calc_done
-add wave stop
 
 #rauszoomen
 wave zoomout 500.0
 
-#simulation starten (1 ms)
-run 1 ms
+#simulation starten und 100ms lang laufen lassen (wird durch assert abgebrochen)
+run -all
 
 #ganz nach links scrollen
 wave seetime 0
+
index de0b6a6aa32c4c0d95cce84bfe13a4edfb032a28..2d9e4a7523ea95df162b0c83e6fd07bf4c385385 100644 (file)
@@ -13,7 +13,6 @@ entity alu is
                op2 : in csigned;
                op3 : out csigned;
                do_calc : in std_logic;
-               ack : in std_logic;
                calc_done : out std_logic
        );
 end entity alu;
@@ -34,25 +33,27 @@ begin
        end process;
 
        -- next state
-       process(state, opcode, done_intern)
+       process(state, opcode, done_intern, do_calc)
        begin
                -- set a default value for next state
                state_next <= state;
                -- next state berechnen
                case state is
                        when SIDLE =>
-                               case opcode is
-                                       when ADD =>
-                                               state_next <= SADD;
-                                       when SUB =>
-                                               state_next <= SSUB;
-                                       when MUL =>
-                                               state_next <= SMUL;
-                                       when DIV =>
-                                               state_next <= SDIV;
-                                       when others =>
-                                               state_next <= SIDLE;
-                               end case;
+                               if do_calc = '1' then
+                                       case opcode is
+                                               when ADD =>
+                                                       state_next <= SADD;
+                                               when SUB =>
+                                                       state_next <= SSUB;
+                                               when MUL =>
+                                                       state_next <= SMUL;
+                                               when DIV =>
+                                                       state_next <= SDIV;
+                                               when others =>
+                                                       state_next <= SIDLE;
+                                       end case;
+                               end if;
                        when SADD =>
                                if done_intern = '1' then
                                        state_next <= SDONE;
@@ -70,7 +71,7 @@ begin
                                        state_next <= SDONE;
                                end if;
                        when SDONE =>
-                               if ack = '1' then
+                               if do_calc = '0' then
                                        state_next <= SIDLE;
                                end if;
                end case;
@@ -78,6 +79,8 @@ begin
 
        -- output
        process(state)
+       variable tmperg : csigned;
+       variable multmp : signed(((2*CBITS)-1) downto 0);
        begin
                op3 <= (others => '0');
                calc_done <= '0';
@@ -86,20 +89,23 @@ begin
                        when SIDLE =>
                                done_intern <= '0';
                        when SADD =>
-                               op3 <= op1 + op2;
+                               tmperg := op1 + op2;
                                done_intern <= '1';
                        when SSUB =>
-                               op3 <= op1 - op2;
+                               tmperg := op1 - op2;
                                done_intern <= '1';
                        when SMUL =>
-                               op3 <= op1 * op2;
+                               multmp := op1 * op2;
+                               tmperg(CBITS-1) := multmp((2*CBITS)-1);
+                               tmperg((CBITS-2) downto 0) := multmp((CBITS-2) downto 0);
                                done_intern <= '1';
                        when SDIV =>
-                               op3 <= op1 / op2;
+                               tmperg := op1 / op2;
                                done_intern <= '1';
                        when SDONE =>
                                done_intern <= '1';
                                calc_done <= '1';
+                               op3 <= tmperg;
                end case;
        end process;
 end architecture beh;
index df488b60ab9adb8fb5b3a698c1760455b4399e7c..33f4455ca6e38db881f4cc6759be877bf9ded21c 100644 (file)
@@ -4,7 +4,7 @@ use ieee.numeric_std.all;
 use work.gen_pkg.all;
 
 entity alu_tb is
-       end entity alu_tb;
+end entity alu_tb;
 
 architecture sim of alu_tb is
        component alu is
@@ -17,14 +17,13 @@ architecture sim of alu_tb is
                        op2 : in csigned;
                        op3 : out csigned;
                        do_calc : in std_logic;
-                       ack : in std_logic;
                        calc_done : out std_logic
                );
        end component alu;
 
-       signal sys_clk, sys_res_n, do_calc, calc_done, ack : std_logic;
+       signal sys_clk, sys_res_n, do_calc, calc_done : std_logic;
        signal opcode : alu_ops;
-       signal op1, op2, op3, optmp : csigned;
+       signal op1, op2, op3 : csigned;
        signal stop : boolean := false;
 begin
        bla : alu
@@ -33,7 +32,6 @@ begin
                sys_clk => sys_clk,
                sys_res_n => sys_res_n,
                do_calc => do_calc,
-               ack => ack,
                calc_done => calc_done,
                op1 => op1,
                op2 => op2,
@@ -46,37 +44,68 @@ begin
                sys_clk <= '0';
                wait for 15 ns;
                sys_clk <= '1';
+               wait for 15 ns;
                if stop = true then
                        wait;
                end if;
-               wait for 15 ns;
        end process;
 
        process
+               type alu_testv is record
+                       o1 : cinteger;
+                       o : alu_ops;
+                       o2 : cinteger;
+                       expected : cinteger;
+               end record alu_testv;
+
+               -- ggf. groesse des arrays erhoehen
+               type alu_testv_array is array (natural range 0 to 20) of alu_testv;
+
+               variable testmatrix : alu_testv_array :=
+                       ( 0 => (7, ADD, 3, 10),
+                         1 => (7, SUB, 1, 6),
+                         2 => (7, DIV, 1, 7),
+                         3 => (7, DIV, 2, 3),
+                         4 => (7, ADD, 1, 8),
+                         5 => (7, MUL, 3, 21),
+                         6 => (-7, MUL, 3, -21),
+                         7 => (268435456, MUL, -2, -536870912),
+                         8 => (268435456, MUL, 2**5, 0), -- um fuenf nach links shiften
+                         9 => (268435456 + 5, MUL, 2**5, 160), -- = 5 * (2^5)
+                         others => (0, ADD, 0, 0)
+                       );
+
        begin
                sys_res_n <= '0';
                wait for 50 ns;
                sys_res_n <= '1';
-               wait for 100 ns;
 
-               op1(31 downto 0) <= (0 => '1', 1 => '1', 2 => '1', others => '0');
-               op2(31 downto 0) <= (0 => '1', 2 => '1', others => '0');
-               opcode <= ADD;
+               for i in testmatrix'range loop
+                       wait for 100 ns;
+                       op1 <= to_signed(testmatrix(i).o1,CBITS);
+                       opcode <= testmatrix(i).o;
+                       op2 <= to_signed(testmatrix(i).o2,CBITS);
 
-               wait for 10 ns;
-               -- berechnung kann los gehen
-               do_calc <= '1';
-               ack <= '0';
+                       -- berechnung kann los gehen
+                       do_calc <= '1';
 
-               -- warten auf die alu einheit
-               wait on calc_done;
+                       -- warten auf die alu einheit
+                       wait on calc_done;
 
-               -- ack it!
-               do_calc <= '0';
-               ack <= '1';
+                       assert op3 = to_signed(testmatrix(i).expected,CBITS)
+                               report "" & cinteger'image(testmatrix(i).o1) & 
+                               " " & alu_ops'image(opcode) &
+                               " " & cinteger'image(testmatrix(i).o2) &
+                               "/= " & integer'image(to_integer(op3)) &
+                               " -- erwartet: " & cinteger'image(testmatrix(i).expected);
 
-               wait for 20 ns;
+                       wait for 5 ns;
+                       -- ack it!
+                       do_calc <= '0';
+               end loop;
 
+               assert false
+                       report "alle testfaelle der ALU waren erfolgreich!";
                stop <= true;
                wait;
        end process;
index cb87dbab6d977aed99c2750d5559556f4b7fc850..37667631f38d6d9da5f79ca1ff8b1b0ec045ef35 100644 (file)
@@ -4,6 +4,9 @@ use ieee.numeric_std.all;
 
 package gen_pkg is
        type alu_ops is (NOP, SUB, ADD, MUL, DIV, DONE);
-       subtype csigned is signed(31 downto 0);
+       constant CBITS : integer := 32;
+       subtype csigned is signed((CBITS-1) downto 0);
+       --TODO: bei CBITS-1 gibts einen overflow :/
+       subtype cinteger is integer range -(2**(CBITS-2)) to ((2**(CBITS-2))-1);
 end package gen_pkg;