---------------------------------------------------------------------------- -- non-restoring divider (nr_divider.vhd) -- -- Used in chapter 4 euclidean modular divider -- -- ---------------------------------------------------------------------------- library IEEE; use IEEE.std_logic_1164.all; use IEEE.std_logic_arith.all; use IEEE.std_logic_unsigned.all; package nr_divider_parameters is constant K: natural := 8; constant COUNTER_SIZE: natural := 3; --log2(K) constant CS_ZERO: std_logic_vector(COUNTER_SIZE-1 downto 0) := (others => '0'); constant ZERO: std_logic_vector(k-1 downto 0) := (others => '0'); constant SHORT_ZERO: std_logic_vector(k-2 downto 0) := (others => '0'); end nr_divider_parameters; ---------------------------------------------------------------------------- -- non-restoring divider ---------------------------------------------------------------------------- library IEEE; use IEEE.std_logic_1164.all; use IEEE.std_logic_arith.all; use IEEE.std_logic_unsigned.all; use work.nr_divider_parameters.all; entity nr_divider is port ( a, b: in std_logic_vector (K-1 downto 0); clk, reset, start: in std_logic; quotient, remainder: out std_logic_vector (K-1 downto 0); done: out std_logic ); end nr_divider; architecture rtl of nr_divider is signal s: std_logic_vector(2*K-1 downto 0); signal r: std_logic_vector(2*K-2 downto 0); signal q: std_logic_vector(K-1 downto 1); signal modified_q: std_logic_vector(K-1 downto 0); signal load, update, equal_zero: std_logic; signal count: std_logic_vector(COUNTER_SIZE -1 downto 0); type states is range 0 to 4; signal current_state: states; begin parallel_register: process(clk) begin if clk'event and clk = '1' then if load = '1' then s <= zero & a; elsif update = '1' then s(2*K-1 downto 1) <= r(2*K-2 downto 0); s(0) <= '0'; end if; end if; end process parallel_register; shift_register: process(clk) begin if clk'event and clk = '1' then if load = '1' then q <= short_zero; elsif update = '1' then for i in K-1 downto 2 loop q(i) <= q(i-1); end loop; q(1) <= not(s(2*K-1)); end if; end if; end process shift_register; with s(2*K-1) select r(2*K-2 downto k-2) <= s(2*K-2 downto k-2) + b when '1', s(2*K-2 downto K-2) - b when others; r(K-3 downto 0) <= s(K-3 downto 0); modified_q <= not(q(K-1))&q(K-2 downto 1)&'1'; with s(2*K-1) select quotient <= modified_q when '0', modified_q -1 when others; with s(2*K-1) select remainder <= s(2*K-2 downto K-1) when '0', s(2*K-2 downto K-1) + b when others; counter: process(clk) begin if clk'event and clk = '1' then if load = '1' then count <= conv_std_logic_vector(K-2, COUNTER_SIZE); elsif update = '1' then count <= count-1; end if; end if; end process counter; with count select equal_zero <= '1' when CS_ZERO, '0' when others; control_unit: process(clk, reset, current_state, equal_zero) begin case current_state is when 0 to 1 => load <= '0'; update <= '0'; done <= '1'; when 2 => load <= '1'; update <= '0'; done <= '0'; when 3 => load <= '0'; update <= '1'; done <= '0'; when 4 => load <= '0'; update <= '0'; done <= '0'; end case; if reset = '1' then current_state <= 0; elsif clk'event and clk = '1' then case current_state is when 0 => if start = '0' then current_state <= 1; end if; when 1 => if start = '1' then current_state <= 2; end if; when 2 => current_state <= 3; when 3 => if equal_zero = '1' then current_state <= 4; end if; when 4 => current_state <= 0; end case; end if; end process; end rtl;