library IEEE; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; entity divider is port ( clk : in std_logic; start : in std_logic; done : out std_logic := '0'; busy : out std_logic := '0'; dividend : in signed(32 downto 0); divisor : in signed(32 downto 0); quotient : out signed(32 downto 0); remainder : out signed(32 downto 0) ); end entity; architecture arch of divider is constant bits_per_cycle : integer := 1; signal dividend_u : unsigned(dividend'length downto 0); signal divisor_u : unsigned(divisor'length downto 0); signal quotient_u : unsigned(quotient'length downto 0); signal Akku : unsigned (divisor'left + 1 downto divisor'right); signal QPointer : integer range quotient_u'range; signal done_buffer : std_logic := '0'; begin process (clk) is variable XPointer : integer range dividend_u'range; variable QPointerNew : integer range quotient_u'range; variable AkkuNew : unsigned (divisor'left + 1 downto divisor'right); variable Rdy_i : std_logic; variable Q_bits : std_logic_vector(bits_per_cycle-1 downto 0); variable Diff : unsigned (AkkuNew'range); begin if rising_edge(clk) then done_buffer <= '0'; busy <= '0'; -- == Initialize loop =============================================== if start = '1' then busy <= '1'; dividend_u <= '0' & unsigned(abs(dividend)); divisor_u <= '0' & unsigned(abs(divisor)); QPointerNew := quotient_u'left; XPointer := dividend_u'left; Rdy_i := '0'; --AkkuNew := (Akku'left downto 1 => '0') & dividend(XPointer); AkkuNew := (others => '0'); -- == Repeat for every Digit in Q =================================== elsif Rdy_i = '0' then busy <= '1'; AkkuNew := Akku; QPointerNew := QPointer; for i in 1 to bits_per_cycle loop -- Calculate output digit and new Akku --------------------------- Diff := AkkuNew - divisor_u; if Diff(Diff'left) = '0' then -- Does Y fit in Akku? Q_bits(bits_per_cycle-i) := '1'; -- YES: Digit is '1' AkkuNew := unsigned(shift_left(Diff,1));-- Diff -> Akku else -- Q_bits(bits_per_cycle-i) := '0'; -- NO : Digit is '0' AkkuNew := unsigned(Shift_left(AkkuNew,1));-- Shift Akku end if; -- --------------------------------------------------------------- if XPointer > dividend'right then -- divisor read completely? XPointer := XPointer - 1; -- NO : Put next digit AkkuNew(AkkuNew'right) := dividend_u(XPointer); -- in Akku else AkkuNew(AkkuNew'right) := '0' ; -- YES: Read Zeros (post point) end if; -- --------------------------------------------------------------- if QPointerNew > quotient'right then -- Has this been the last cycle? QPointerNew := QPointerNew - 1; -- NO : Prepare next cycle else -- Rdy_i := '1'; -- YES: work done done_buffer <= '1'; end if; end loop; quotient_u(QPointer downto QPointer-(bits_per_cycle-1)) <= unsigned(Q_bits); end if; QPointer <= QPointerNew; Akku <= AkkuNew; if ((dividend(dividend'left) xor divisor(divisor'left)) = '1') then quotient <= -signed(quotient_u(quotient'left downto 0)); else quotient <= signed(quotient_u(quotient'left downto 0)); end if; if (dividend(dividend'left) = '1') then remainder <= -signed(AkkuNew(remainder'left + 1 downto remainder'right + 1)); else remainder <= signed(AkkuNew(remainder'left + 1 downto remainder'right + 1)); end if; done <= done_buffer; end if; end process; end architecture;