X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Falu.vhd;h=f3eb81c815f5277cbdf5d1597ee93d8d094c619f;hb=65a0faac261dd81bfd50bbac5794656af92626b3;hp=014fc766c6f0210f219d1cddd57373cebc9c9304;hpb=e4d17ff9b56af5b05d5b610bac24127f697c8419;p=hwmod.git diff --git a/src/alu.vhd b/src/alu.vhd index 014fc76..f3eb81c 100644 --- a/src/alu.vhd +++ b/src/alu.vhd @@ -20,12 +20,9 @@ entity alu is end entity alu; architecture beh of alu is - type ALU_STATE is (SIDLE, SADD, SSUB, SMUL, SDIV, SDIV_CALC, SDIV_DONE, - SDONE, SERROR); + type ALU_STATE is (SIDLE, SADD, SSUB, SMUL, SDIV, SDIV_CALC, SDONE, SERROR); signal state_int, state_next : ALU_STATE; signal done_intern, error_intern : std_logic; - signal div_calc_done_int : std_logic; - signal div_calc_done2_int : std_logic; signal div_go_calc_int : std_logic; signal op3_int, op3_next, opM_int, opM_next : csigned; signal calc_done_int, calc_done_next : std_logic; @@ -50,8 +47,8 @@ begin calc_done_int <= '0'; calc_error_int <= '0'; --div - dividend_msb_int <= 0; - laengediv_int <= 0; + dividend_msb_int <= (others => '0'); + laengediv_int <= (others => '0'); quo_int <= (others => '0'); aktdiv_int <= (others => '0'); op1_int <= (others => '0'); @@ -75,8 +72,7 @@ begin end process; -- next state - process(state_int, opcode, done_intern, error_intern, do_calc, - div_calc_done_int, div_calc_done2_int, div_go_calc_int) + process(state_int, opcode, done_intern, error_intern, do_calc, div_go_calc_int) begin -- set a default value for next state state_next <= state_int; @@ -85,39 +81,27 @@ begin when SIDLE => if do_calc = '1' then case opcode is - when ALU_ADD => - state_next <= SADD; - when ALU_SUB => - state_next <= SSUB; - when ALU_MUL => - state_next <= SMUL; - when ALU_DIV => - state_next <= SDIV; - when others => - state_next <= SIDLE; + when ALU_ADD => state_next <= SADD; + when ALU_SUB => state_next <= SSUB; + when ALU_MUL => state_next <= SMUL; + when ALU_DIV => state_next <= SDIV; + when others => state_next <= SIDLE; end case; end if; - when SADD | SSUB | SMUL | SDIV_DONE => + when SADD | SSUB | SMUL | SDIV | SDIV_CALC => + case state_int is + when SDIV => + if div_go_calc_int = '1' then + state_next <= SDIV_CALC; + end if; + when others => null; + end case; if done_intern = '1' then state_next <= SDONE; end if; if error_intern = '1' then state_next <= SERROR; end if; - when SDIV => - if div_go_calc_int = '1' then - state_next <= SDIV_CALC; - end if; - if div_calc_done2_int = '1' then - state_next <= SDIV_DONE; - end if; - if error_intern = '1' then - state_next <= SERROR; - end if; - when SDIV_CALC => - if div_calc_done_int = '1' then - state_next <= SDIV_DONE; - end if; when SDONE | SERROR => if do_calc = '0' then state_next <= SIDLE; @@ -137,14 +121,12 @@ begin begin calc_done_next <= '0'; calc_error_next <= '0'; - div_calc_done_int <= '0'; - div_calc_done2_int <= '0'; div_go_calc_int <= '0'; done_intern <= '0'; error_intern <= '0'; -- default fuer div - dividend_msb_next <= 0; - laengediv_next <= 0; + dividend_msb_next <= (others => '0'); + laengediv_next <= (others => '0'); quo_next <= (others => '0'); aktdiv_int_next <= aktdiv_int; op1_next <= (others => '0'); @@ -210,15 +192,23 @@ begin op2_var := (not op2_var) + 1; end if; - dividend_msb_var := find_msb(op1_var)-1; - laengediv_var := find_msb(op2_var)-1; + dividend_msb_var := divinteger(find_msb(std_logic_vector(op1_var)))-1; + laengediv_var := divinteger(find_msb(std_logic_vector(op2_var)))-1; - aktdiv_int_next <= op1_var srl (dividend_msb_var - laengediv_var + 1); + aktdiv_int_next <= op1_var srl to_integer(dividend_msb_var - laengediv_var + 1); - if op1_var < op2_var then - div_calc_done2_int <= '1'; - quo_next <= to_signed(0,CBITS); - aktdiv_int_next <= op1_var; + -- anmerkung: xst (xilinx) kann folgende zeile nicht uebersetzen + -- > if op1 = to_signed(-2147483648, CBITS) then + -- darum folgende schreibweise -> + if op1 = x"80000000" then + -- so ziemlich das boeseste was passieren kann + done_intern <= '1'; + op3_next <= to_signed(-214748364,CBITS); + opM_next <= to_signed(8,CBITS); + elsif (op1_var < op2_var) then + done_intern <= '1'; + op3_next <= to_signed(0,CBITS); + opM_next <= op1_var; else div_go_calc_int <= '1'; dividend_msb_next <= dividend_msb_var; @@ -234,7 +224,7 @@ begin if divtmp > 0 then aktdiv_int_var := aktdiv_int sll 1; - aktdiv_int_var(0) := op1_int(divtmp - 1); + aktdiv_int_var(0) := op1_int(to_integer(divtmp) - 1); quo_var := quo_int sll 1; if aktdiv_int_var >= op2_int then @@ -251,16 +241,13 @@ begin sign_next <= sign_int; else if sign_int = '1' then - quo_next <= (not quo_int) + 1; + op3_next <= (not quo_int) + 1; else - quo_next <= quo_int; + op3_next <= quo_int; end if; - div_calc_done_int <= '1'; + opM_next <= aktdiv_int; + done_intern <= '1'; end if; - when SDIV_DONE => - op3_next <= quo_int; - opM_next <= aktdiv_int; - done_intern <= '1'; when SDONE | SERROR => calc_done_next <= '1'; if (state_int = SERROR) then