X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Falu.vhd;h=eae611655d3d63dad7f1d9ca963f755a5c0e4b9c;hb=a302dda905ac28ab6ac54649be070880002388b1;hp=fad995e48a94dcdbbcb17065132137233f6a0fcc;hpb=8b036ef70262c5a6071fe214fc9984ec5a0d7b0c;p=hwmod.git diff --git a/src/alu.vhd b/src/alu.vhd index fad995e..eae6116 100644 --- a/src/alu.vhd +++ b/src/alu.vhd @@ -18,11 +18,15 @@ entity alu is end entity alu; architecture beh of alu is - type ALU_STATE is (SIDLE, SADD, SSUB, SMUL, SDIV, SDONE); + type ALU_STATE is (SIDLE, SADD, SSUB, SMUL, SDIV, SDIV_CALC, SDIV_DONE, SDONE); signal state, state_next : ALU_STATE; - signal done_intern : std_logic; + 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; begin op3 <= op3_int; calc_done <= calc_done_int; @@ -36,11 +40,19 @@ begin state <= state_next; op3_int <= op3_next; calc_done_int <= calc_done_next; + -- div + dividend_msb <= dividend_msb_next; + laengediv <= laengediv_next; + quo <= quo_next; + aktdiv <= aktdiv_next; + op1_int <= op1_next; + op2_int <= op2_next; + sign <= sign_next; end if; end process; -- next state - process(state, opcode, done_intern, do_calc) + process(state, opcode, done_intern, do_calc, div_calc_done, div_go_calc) begin -- set a default value for next state state_next <= state; @@ -74,6 +86,14 @@ begin state_next <= SDONE; end if; when SDIV => + if div_go_calc = '1' then + state_next <= SDIV_CALC; + end if; + when SDIV_CALC => + if div_calc_done = '1' then + state_next <= SDIV_DONE; + end if; + when SDIV_DONE => if done_intern = '1' then state_next <= SDONE; end if; @@ -85,17 +105,30 @@ begin end process; -- output - process(state, op1, op2) - variable tmperg : csigned; - variable multmp : signed(((2*CBITS)-1) downto 0); + process(state, op1, op2, dividend_msb, laengediv, quo, aktdiv, sign, op1_int, op2_int) + variable tmperg : csigned; + variable multmp : signed(((2*CBITS)-1) downto 0); + -- vars fuer div + variable laengediv_var, dividend_msb_var : natural; + variable aktdiv_var, quo_var, op1_var, op2_var : csigned; begin op3_next <= (others => '0'); calc_done_next <= '0'; + div_calc_done <= '0'; + div_go_calc <= '0'; + done_intern <= '0'; + -- default fuer div + dividend_msb_next <= 0; + laengediv_next <= 0; + quo_next <= (others => '0'); + aktdiv_next <= (others => '0'); + op1_next <= (others => '0'); + op2_next <= (others => '0'); + sign_next <= '0'; case state is when SIDLE => tmperg := (others => '0'); - done_intern <= '0'; when SADD => tmperg := op1 + op2; done_intern <= '1'; @@ -108,7 +141,65 @@ begin tmperg((CBITS-2) downto 0) := multmp((CBITS-2) downto 0); done_intern <= '1'; when SDIV => - tmperg := op1 / op2; + -- division implementiert nach ~hwmod/doc/division.pdf + tmperg := (others => '0'); + if op2 = to_signed(0,CBITS) then + -- TODO: err out signal + done_intern <= '1'; + else + -- sign check + op1_var := op1; + op2_var := op2; + if op1(CBITS-1) = '1' then + op1_var := not (op1_var + 1); + end if; + if op2(CBITS-1) = '1' then + op2_var := not (op2_var + 1); + end if; + + dividend_msb_var := find_msb(op1_var)-1; + laengediv_var := find_msb(op2_var)-1; + + aktdiv_next <= op1_var srl (dividend_msb_var - laengediv_var + 1); + + div_go_calc <= '1'; + dividend_msb_next <= dividend_msb_var; + laengediv_next <= laengediv_var; + quo_next <= (others => '0'); + op1_next <= op1_var; + op2_next <= op2_var; + sign_next <= op1(CBITS-1) xor op2(CBITS-1); + end if; + when SDIV_CALC => + tmperg := (others => '0'); + + if (dividend_msb - laengediv + 1) > 0 then + aktdiv_var := aktdiv sll 1; + aktdiv_var(0) := op1_int(dividend_msb - laengediv); + + quo_var := quo sll 1; + if aktdiv_var >= op2_int then + quo_var(0) := '1'; + aktdiv_var := aktdiv_var - op2_int; + end if; + + quo_next <= quo_var; + aktdiv_next <= aktdiv_var; + dividend_msb_next <= dividend_msb; + laengediv_next <= laengediv + 1; + op1_next <= op1_int; + op2_next <= op2_int; + sign_next <= sign; + else + if sign = '1' then + quo_next <= (not quo) + 1; + else + quo_next <= quo; + end if; + div_calc_done <= '1'; + end if; + when SDIV_DONE => + tmperg := quo; done_intern <= '1'; when SDONE => done_intern <= '1'; @@ -118,3 +209,4 @@ begin end case; end process; end architecture beh; +