laut lva-leitung soll man keine enums im interface verwenden.
op3 : out csigned;
do_calc : in std_logic;
calc_done : out std_logic
+ -- TODO: hier debug ports hinzufuegen ;)
);
end entity alu;
architecture beh of alu is
type ALU_STATE is (SIDLE, SADD, SSUB, SMUL, SDIV, SDIV_CALC, SDIV_DONE, SDONE);
- signal state, state_next : ALU_STATE;
+ signal state_int, state_next : ALU_STATE;
signal done_intern, div_calc_done, div_go_calc : std_logic;
signal op3_int, op3_next : csigned;
signal calc_done_int, calc_done_next : std_logic;
-- signale fuer division
- signal dividend_msb, dividend_msb_next, laengediv, laengediv_next : natural;
- signal quo, quo_next, aktdiv, aktdiv_next, op1_int, op1_next, op2_int, op2_next : csigned;
- signal sign, sign_next : std_logic;
+ signal dividend_msb_int, dividend_msb_next, laengediv_int, laengediv_next : natural;
+ signal quo_int, quo_next, aktdiv, aktdiv_next, op1_int, op1_next, op2_int, op2_next : csigned;
+ signal sign_int, sign_next : std_logic;
begin
op3 <= op3_int;
calc_done <= calc_done_int;
process(sys_clk, sys_res_n)
begin
if sys_res_n = '0' then
- state <= SIDLE;
+ state_int <= SIDLE;
op3_int <= (others => '0');
calc_done_int <= '0';
--div
- dividend_msb <= 0;
- laengediv <= 0;
- quo <= (others => '0');
+ dividend_msb_int <= 0;
+ laengediv_int <= 0;
+ quo_int <= (others => '0');
aktdiv <= (others => '0');
op1_int <= (others => '0');
op2_int <= (others => '0');
- sign <= '0';
+ sign_int <= '0';
elsif rising_edge(sys_clk) then
- state <= state_next;
+ state_int <= state_next;
op3_int <= op3_next;
calc_done_int <= calc_done_next;
-- div
- dividend_msb <= dividend_msb_next;
- laengediv <= laengediv_next;
- quo <= quo_next;
+ dividend_msb_int <= dividend_msb_next;
+ laengediv_int <= laengediv_next;
+ quo_int <= quo_next;
aktdiv <= aktdiv_next;
op1_int <= op1_next;
op2_int <= op2_next;
- sign <= sign_next;
+ sign_int <= sign_next;
end if;
end process;
-- next state
- process(state, opcode, done_intern, do_calc, div_calc_done, div_go_calc)
+ process(state_int, opcode, done_intern, do_calc, div_calc_done, div_go_calc)
begin
-- set a default value for next state
- state_next <= state;
+ state_next <= state_int;
-- next state berechnen
- case state is
+ case state_int is
when SIDLE =>
if do_calc = '1' then
case opcode is
- when ADD =>
+ when ALU_ADD =>
state_next <= SADD;
- when SUB =>
+ when ALU_SUB =>
state_next <= SSUB;
- when MUL =>
+ when ALU_MUL =>
state_next <= SMUL;
- when DIV =>
+ when ALU_DIV =>
state_next <= SDIV;
when others =>
state_next <= SIDLE;
end process;
-- output
- process(state, op1, op2, dividend_msb, laengediv, quo, aktdiv, sign, op1_int, op2_int)
+ process(state_int, op1, op2, dividend_msb_int, laengediv_int, quo_int, aktdiv, sign_int, op1_int, op2_int)
variable tmperg : csigned;
variable multmp : signed(((2*CBITS)-1) downto 0);
-- vars fuer div
op2_next <= (others => '0');
sign_next <= '0';
- case state is
+ case state_int is
when SIDLE =>
tmperg := (others => '0');
when SADD =>
when SDIV_CALC =>
tmperg := (others => '0');
- if (dividend_msb - laengediv + 1) > 0 then
+ if (dividend_msb_int - laengediv_int + 1) > 0 then
aktdiv_var := aktdiv sll 1;
- aktdiv_var(0) := op1_int(dividend_msb - laengediv);
+ aktdiv_var(0) := op1_int(dividend_msb_int - laengediv_int);
- quo_var := quo sll 1;
+ quo_var := quo_int sll 1;
if aktdiv_var >= op2_int then
quo_var(0) := '1';
aktdiv_var := aktdiv_var - op2_int;
quo_next <= quo_var;
aktdiv_next <= aktdiv_var;
- dividend_msb_next <= dividend_msb;
- laengediv_next <= laengediv + 1;
+ dividend_msb_next <= dividend_msb_int;
+ laengediv_next <= laengediv_int + 1;
op1_next <= op1_int;
op2_next <= op2_int;
- sign_next <= sign;
+ sign_next <= sign_int;
else
- if sign = '1' then
- quo_next <= (not quo) + 1;
+ if sign_int = '1' then
+ quo_next <= (not quo_int) + 1;
else
- quo_next <= quo;
+ quo_next <= quo_int;
end if;
div_calc_done <= '1';
end if;
when SDIV_DONE =>
- tmperg := quo;
+ tmperg := quo_int;
done_intern <= '1';
when SDONE =>
done_intern <= '1';
type alu_testv_array is array (natural range 0 to 20) of alu_testv;
variable testmatrix : alu_testv_array :=
- ( 0 => (-5, DIV, 3, -1),
- 1 => (7, ADD, 3, 10),
- 2 => (7, SUB, 1, 6),
- 3 => (7, DIV, 1, 7),
- 4 => (7, DIV, 3, 2),
- 5 => (7, ADD, 1, 8),
- 6 => (7, MUL, 3, 21),
- 7 => (-7, MUL, 3, -21),
- 8 => (268435456, MUL, -2, -536870912),
- 9 => (268435456, MUL, 2**5, 0), -- um fuenf nach links shiften
- 10 => (268435456 + 5, MUL, 2**5, 160), -- = 5 * (2^5)
- 11 => (100, DIV, 10, 10),
- 12 => (100, DIV, 51, 1),
- 13 => (100, DIV, 49, 2),
- 14 => (153156, DIV, 3543, 43),
- 15 => (-153156, DIV, 3543, -43),
- 16 => (153156, DIV, -3543, -43),
- 17 => (-153156, DIV, -3543, 43),
- others => (0, ADD, 0, 0)
+ ( 0 => (-5, ALU_DIV, 3, -1),
+ 1 => (7, ALU_ADD, 3, 10),
+ 2 => (7, ALU_SUB, 1, 6),
+ 3 => (7, ALU_DIV, 1, 7),
+ 4 => (7, ALU_DIV, 3, 2),
+ 5 => (7, ALU_ADD, 1, 8),
+ 6 => (7, ALU_MUL, 3, 21),
+ 7 => (-7, ALU_MUL, 3, -21),
+ 8 => (268435456, ALU_MUL, -2, -536870912),
+ 9 => (268435456, ALU_MUL, 2**5, 0), -- um fuenf nach links shiften
+ 10 => (268435456 + 5, ALU_MUL, 2**5, 160), -- = 5 * (2^5)
+ 11 => (100, ALU_DIV, 10, 10),
+ 12 => (100, ALU_DIV, 51, 1),
+ 13 => (100, ALU_DIV, 49, 2),
+ 14 => (153156, ALU_DIV, 3543, 43),
+ 15 => (-153156, ALU_DIV, 3543, -43),
+ 16 => (153156, ALU_DIV, -3543, -43),
+ 17 => (-153156, ALU_DIV, -3543, 43),
+ others => (0, ALU_ADD, 0, 0)
);
begin
assert op3 = to_signed(testmatrix(i).expected,CBITS)
report "" & cinteger'image(testmatrix(i).o1) &
- " " & alu_ops'image(opcode) &
+ " " & integer'image(to_integer(signed(opcode))) &
" " & cinteger'image(testmatrix(i).o2) &
"/= " & integer'image(to_integer(op3)) &
" -- erwartet: " & cinteger'image(testmatrix(i).expected);
use ieee.numeric_std.all;
package gen_pkg is
- type alu_ops is (NOP, SUB, ADD, MUL, DIV, DONE);
+ subtype alu_ops is std_logic_vector(2 downto 0);
+ constant ALU_NOP : alu_ops := "000";
+ constant ALU_SUB : alu_ops := "001";
+ constant ALU_ADD : alu_ops := "010";
+ constant ALU_MUL : alu_ops := "011";
+ constant ALU_DIV : alu_ops := "100";
+ constant ALU_DONE : alu_ops := "101";
+
constant CBITS : integer := 32;
subtype csigned is signed((CBITS-1) downto 0);
--TODO: bei CBITS-1 gibts einen overflow :/
add wave op3
add wave do_calc
add wave calc_done
-add wave \\opcode.NOP\\
-add wave \\opcode.SUB\\
-add wave \\opcode.ADD\\
-add wave \\opcode.MUL\\
-add wave \\opcode.DIV\\
-add wave \\opcode.DONE\\
#rauszoomen
wave zoomout 500.0
(
sys_clk : in std_logic;
sys_res_n : in std_logic;
- \opcode.NOP\ : in std_logic;
- \opcode.SUB\ : in std_logic;
- \opcode.ADD\ : in std_logic;
- \opcode.MUL\ : in std_logic;
- \opcode.DIV\ : in std_logic;
- \opcode.DONE\ : 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);
signal sys_clk, sys_res_n, do_calc, calc_done : std_logic;
signal opcode : alu_ops;
- signal \opcode.NOP\ : std_logic;
- signal \opcode.SUB\ : std_logic;
- signal \opcode.ADD\ : std_logic;
- signal \opcode.MUL\ : std_logic;
- signal \opcode.DIV\ : std_logic;
- signal \opcode.DONE\ : std_logic;
signal op1, op2, op3 : std_logic_vector(31 downto 0);
signal stop : boolean := false;
begin
op1 => op1,
op2 => op2,
op3 => op3,
- \opcode.NOP\ => \opcode.NOP\,
- \opcode.SUB\ => \opcode.SUB\,
- \opcode.ADD\ => \opcode.ADD\,
- \opcode.MUL\ => \opcode.MUL\,
- \opcode.DIV\ => \opcode.DIV\,
- \opcode.DONE\ => \opcode.DONE\
+ opcode => opcode
);
process
begin
sys_clk <= '0';
- wait for 15 ns;
+ wait for 20 ns;
sys_clk <= '1';
- wait for 15 ns;
+ wait for 20 ns;
if stop = true then
wait;
end if;
type alu_testv_array is array (natural range 0 to 20) of alu_testv;
variable testmatrix : alu_testv_array :=
- ( 0 => (-5, DIV, 3, -1),
- 1 => (7, ADD, 3, 10),
- 2 => (7, SUB, 1, 6),
- 3 => (7, DIV, 1, 7),
- 4 => (7, DIV, 3, 2),
- 5 => (7, ADD, 1, 8),
- 6 => (7, MUL, 3, 21),
- 7 => (-7, MUL, 3, -21),
- 8 => (268435456, MUL, -2, -536870912),
- 9 => (268435456, MUL, 2**5, 0), -- um fuenf nach links shiften
- 10 => (268435456 + 5, MUL, 2**5, 160), -- = 5 * (2^5)
- 11 => (100, DIV, 10, 10),
- 12 => (100, DIV, 51, 1),
- 13 => (100, DIV, 49, 2),
- 14 => (153156, DIV, 3543, 43),
- 15 => (-153156, DIV, 3543, -43),
- 16 => (153156, DIV, -3543, -43),
- 17 => (-153156, DIV, -3543, 43),
- others => (0, ADD, 0, 0)
+ ( 0 => (-5, ALU_DIV, 3, -1),
+ 1 => (7, ALU_ADD, 3, 10),
+ 2 => (7, ALU_SUB, 1, 6),
+ 3 => (7, ALU_DIV, 1, 7),
+ 4 => (7, ALU_DIV, 3, 2),
+ 5 => (7, ALU_ADD, 1, 8),
+ 6 => (7, ALU_MUL, 3, 21),
+ 7 => (-7, ALU_MUL, 3, -21),
+ 8 => (268435456, ALU_MUL, -2, -536870912),
+ 9 => (268435456, ALU_MUL, 2**5, 0), -- um fuenf nach links shiften
+ 10 => (268435456 + 5, ALU_MUL, 2**5, 160), -- = 5 * (2^5)
+ 11 => (100, ALU_DIV, 10, 10),
+ 12 => (100, ALU_DIV, 51, 1),
+ 13 => (100, ALU_DIV, 49, 2),
+ 14 => (153156, ALU_DIV, 3543, 43),
+ 15 => (-153156, ALU_DIV, 3543, -43),
+ 16 => (153156, ALU_DIV, -3543, -43),
+ 17 => (-153156, ALU_DIV, -3543, 43),
+ others => (0, ALU_ADD, 0, 0)
);
begin
+ -- init & reset
sys_res_n <= '0';
- wait for 50 ns;
+ do_calc <= '0';
+ opcode <= ALU_NOP;
+ op1 <= (others => '0');
+ op2 <= (others => '0');
+
+ wait for 240 ns;
sys_res_n <= '1';
for i in testmatrix'range loop
wait for 100 ns;
- \opcode.NOP\ <= '0';
- \opcode.SUB\ <= '0';
- \opcode.ADD\ <= '0';
- \opcode.MUL\ <= '0';
- \opcode.DIV\ <= '0';
- \opcode.DONE\ <= '0';
op1 <= std_logic_vector(to_signed(testmatrix(i).o1,CBITS));
- case testmatrix(i).o is
- when NOP => \opcode.NOP\ <= '1';
- when SUB => \opcode.SUB\ <= '1';
- when ADD => \opcode.ADD\ <= '1';
- when MUL => \opcode.MUL\ <= '1';
- when DIV => \opcode.DIV\ <= '1';
- when DONE => \opcode.DONE\ <= '1';
- end case;
+ opcode <= testmatrix(i).o;
op2 <= std_logic_vector(to_signed(testmatrix(i).o2,CBITS));
-- berechnung kann los gehen
-- warten auf die alu einheit
wait on calc_done;
+ wait for 80 ns;
assert op3 = std_logic_vector(to_signed(testmatrix(i).expected,CBITS))
report "" & cinteger'image(testmatrix(i).o1) &
- " " & alu_ops'image(opcode) &
+ " " & integer'image(to_integer(signed(opcode))) &
" " & cinteger'image(testmatrix(i).o2) &
"/= " & integer'image(to_integer(signed(op3))) &
" -- erwartet: " & cinteger'image(testmatrix(i).expected);