library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; use work.gen_pkg.all; entity alu is port ( sys_clk : in std_logic; sys_res_n : in std_logic; opcode : in alu_ops; op1 : in csigned; op2 : in csigned; op3 : out csigned; do_calc : in std_logic; calc_done : out std_logic ); end entity alu; architecture beh of alu is type ALU_STATE is (SIDLE, SADD, SSUB, SMUL, SDIV, SDONE); signal state, state_next : ALU_STATE; signal done_intern : std_logic; signal op3_int, op3_next : csigned; signal calc_done_int, calc_done_next : std_logic; begin op3 <= op3_int; calc_done <= calc_done_int; -- sync process(sys_clk, sys_res_n) begin if sys_res_n = '0' then state <= SIDLE; elsif rising_edge(sys_clk) then state <= state_next; op3_int <= op3_next; calc_done_int <= calc_done_next; end if; end process; -- next state 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 => 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; end if; when SSUB => if done_intern = '1' then state_next <= SDONE; end if; when SMUL => if done_intern = '1' then state_next <= SDONE; end if; when SDIV => if done_intern = '1' then state_next <= SDONE; end if; when SDONE => if do_calc = '0' then state_next <= SIDLE; end if; end case; end process; -- output process(state, op1, op2) variable tmperg : csigned; variable multmp : signed(((2*CBITS)-1) downto 0); begin op3_next <= (others => '0'); calc_done_next <= '0'; case state is when SIDLE => tmperg := (others => '0'); done_intern <= '0'; when SADD => tmperg := op1 + op2; done_intern <= '1'; when SSUB => tmperg := op1 - op2; done_intern <= '1'; when SMUL => 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 => tmperg := op1 / op2; done_intern <= '1'; when SDONE => done_intern <= '1'; calc_done_next <= '1'; op3_next <= tmperg; tmperg := (others => '0'); end case; end process; end architecture beh;