2 use ieee.std_logic_1164.all;
3 use ieee.numeric_std.all;
9 sys_clk : in std_logic;
10 sys_res_n : in std_logic;
15 do_calc : in std_logic;
16 calc_done : out std_logic;
17 calc_error : out std_logic
21 architecture beh of alu is
22 type ALU_STATE is (SIDLE, SADD, SSUB, SMUL, SDIV, SDIV_CALC, SDIV_DONE,
24 signal state_int, state_next : ALU_STATE;
25 signal done_intern, error_intern, div_calc_done, div_go_calc : std_logic;
26 signal op3_int, op3_next : csigned;
27 signal calc_done_int, calc_done_next : std_logic;
28 signal calc_error_int, calc_error_next : std_logic;
29 -- signale fuer division
30 signal dividend_msb_int, dividend_msb_next, laengediv_int, laengediv_next : natural;
31 signal quo_int, quo_next, aktdiv_int, aktdiv_int_next, op1_int, op1_next, op2_int, op2_next : csigned;
32 signal sign_int, sign_next : std_logic;
35 calc_done <= calc_done_int;
36 calc_error <= calc_error_int;
39 process(sys_clk, sys_res_n)
41 if sys_res_n = '0' then
43 op3_int <= (others => '0');
45 calc_error_int <= '0';
47 dividend_msb_int <= 0;
49 quo_int <= (others => '0');
50 aktdiv_int <= (others => '0');
51 op1_int <= (others => '0');
52 op2_int <= (others => '0');
54 elsif rising_edge(sys_clk) then
55 state_int <= state_next;
57 calc_done_int <= calc_done_next;
58 calc_error_int <= calc_error_next;
60 dividend_msb_int <= dividend_msb_next;
61 laengediv_int <= laengediv_next;
63 aktdiv_int <= aktdiv_int_next;
66 sign_int <= sign_next;
71 process(state_int, opcode, done_intern, error_intern, do_calc,
72 div_calc_done, div_go_calc)
74 -- set a default value for next state
75 state_next <= state_int;
76 -- next state berechnen
93 when SADD | SSUB | SMUL | SDIV_DONE =>
94 if done_intern = '1' then
97 if error_intern = '1' then
101 if div_go_calc = '1' then
102 state_next <= SDIV_CALC;
104 if error_intern = '1' then
105 state_next <= SERROR;
108 if div_calc_done = '1' then
109 state_next <= SDIV_DONE;
111 when SDONE | SERROR =>
112 if do_calc = '0' then
119 process(state_int, op1, op2, dividend_msb_int, laengediv_int, quo_int, aktdiv_int, sign_int, op1_int, op2_int, op3_int)
120 variable multmp, multmp2 : signed(((2*CBITS)-1) downto 0);
121 variable mulsign : std_logic;
122 variable tmp : csigned;
124 variable laengediv_var, dividend_msb_var : natural;
125 variable aktdiv_int_var, quo_var, op1_var, op2_var : csigned;
127 calc_done_next <= '0';
128 calc_error_next <= '0';
129 div_calc_done <= '0';
134 dividend_msb_next <= 0;
136 quo_next <= (others => '0');
137 aktdiv_int_next <= (others => '0');
138 op1_next <= (others => '0');
139 op2_next <= (others => '0');
150 -- over- bzw. underflow?
151 if (op1(CBITS-1) = op2(CBITS-1)) and (op1(CBITS-1) /= tmp(CBITS -1)) then
160 -- over- bzw. underflow?
161 if (op1(CBITS-1) /= op2(CBITS-1)) and (op1(CBITS-1) /= tmp(CBITS -1)) then
167 mulsign := op1(CBITS-1) xor op2(CBITS-1);
169 op3_next((CBITS-2) downto 0) <= multmp((CBITS-2) downto 0);
170 op3_next(CBITS-1) <= mulsign;
172 if mulsign = '1' then
173 multmp2 := (not multmp) + 1;
178 if(multmp2((2*CBITS)-2 downto (CBITS-1)) > 0) then
185 -- division implementiert nach ~hwmod/doc/division.pdf
186 if ((op1 = x"80000000" and op2 = to_signed(-1, CBITS)) or op2 = to_signed(0, CBITS)) then
192 if op1(CBITS-1) = '1' then
193 op1_var := (not op1_var) + 1;
195 if op2(CBITS-1) = '1' then
196 op2_var := (not op2_var) + 1;
199 dividend_msb_var := find_msb(op1_var)-1;
200 laengediv_var := find_msb(op2_var)-1;
202 aktdiv_int_next <= op1_var srl (dividend_msb_var - laengediv_var + 1);
205 dividend_msb_next <= dividend_msb_var;
206 laengediv_next <= laengediv_var;
207 quo_next <= (others => '0');
210 sign_next <= op1(CBITS-1) xor op2(CBITS-1);
213 if (dividend_msb_int - laengediv_int + 1) > 0 then
214 aktdiv_int_var := aktdiv_int sll 1;
215 aktdiv_int_var(0) := op1_int(dividend_msb_int - laengediv_int);
217 quo_var := quo_int sll 1;
218 if aktdiv_int_var >= op2_int then
220 aktdiv_int_var := aktdiv_int_var - op2_int;
224 aktdiv_int_next <= aktdiv_int_var;
225 dividend_msb_next <= dividend_msb_int;
226 laengediv_next <= laengediv_int + 1;
229 sign_next <= sign_int;
231 if sign_int = '1' then
232 quo_next <= (not quo_int) + 1;
236 div_calc_done <= '1';
241 when SDONE | SERROR =>
242 calc_done_next <= '1';
243 if (state_int = SERROR) then
244 calc_error_next <= '1';
248 end architecture beh;