---------------------------------------------------------------------------- -- Binary algorithm for modular divison (binary_algorithm.vhd) -- ---------------------------------------------------------------------------- library IEEE; use IEEE.std_logic_1164.all; use IEEE.std_logic_arith.all; use IEEE.std_logic_unsigned.all; package binary_algorithm_parameters is -- constant K: natural := 192; -- constant P: std_logic_vector(K-1 downto 0) := x"fffffffffffffffffffffffffffffffeffffffffffffffff"; -- constant K: natural := 256; -- constant P: std_logic_vector(K-1 downto 0) := (223 downto 193 => '0',191 downto 96 => '0',others =>'1'); constant K: natural := 8; constant P: std_logic_vector(K-1 downto 0) := conv_std_logic_vector(239, K); constant ZERO: std_logic_vector(K-1 downto 0) := (others => '0'); constant ONE: std_logic_vector(K-1 downto 0) := conv_std_logic_vector(1, K); end binary_algorithm_parameters; ---------------------------------------------------------------------------- -- subtractor ---------------------------------------------------------------------------- library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; use work.binary_algorithm_parameters.all; entity subtractor is port ( x, y: in std_logic_vector(K-1 downto 0); z: out std_logic_vector(K-1 downto 0) ); end subtractor; architecture rtl of subtractor is signal long_x, not_y, sum1: std_logic_vector(k downto 0); signal c1: std_logic; signal z1, z2: std_logic_vector(K-1 downto 0); begin long_x <= '0'&x; not_gates: for i in 0 to K-1 generate not_y(i) <= not(y(i)); end generate; not_y(K) <= '0'; sum1 <= 1 + long_x + not_y; c1 <= sum1(K); z1 <= sum1(K-1 downto 0); z2 <= z1 + p; with c1 select z <= z1 when '1', z2 when others; end rtl; ---------------------------------------------------------------------------- -- binary_algorithm ---------------------------------------------------------------------------- library IEEE; use IEEE.std_logic_1164.all; use IEEE.std_logic_arith.all; use IEEE.std_logic_unsigned.all; use work.binary_algorithm_parameters.all; entity binary_algorithm is port( x, y: in std_logic_vector(K-1 downto 0); clk, reset, start: in std_logic; z: out std_logic_vector(K-1 downto 0); done: out std_logic ); end binary_algorithm; architecture rtl of binary_algorithm is component subtractor is port ( x, y: in std_logic_vector(K-1 downto 0); z: out std_logic_vector(K-1 downto 0) ); end component; signal a, b, c, d, a_minus_b, ab, ba_minus_ab, cd, d_minus_c, c_minus_d, dc_minus_cd, half_b, half_d, next_a, next_b, next_c, next_d: std_logic_vector(K-1 downto 0); signal long_a, long_b, b_minus_a, long_d, p_by_d0, d_plus_p: std_logic_vector(K downto 0); signal sign, ce, a_equal_1, b_0: std_logic; signal sel: std_logic_vector(1 downto 0); type states is range 0 to 3; signal current_state: states; begin long_b <= '0' & b; long_a <= '0' & a; long_d <= '0' & d; b_minus_a <= long_b - long_a; sign <= b_minus_a(K); a_minus_b <= a - b; with sign select ba_minus_ab <= b_minus_a(K-1 downto 0) when '0', a_minus_b when others; with sign select ab <= a when '0', b when others; and_gates: for i in 0 to K-1 generate p_by_d0(i) <= d(0) and p(i); end generate; p_by_d0(K) <= '0'; d_plus_p <= long_d + p_by_d0; divide_by_2: for i in 0 to K-1 generate half_d(i) <= d_plus_p(i+1); end generate; subtractor1: subtractor port map(d, c, d_minus_c); subtractor2: subtractor port map(c, d, c_minus_d); with sign select dc_minus_cd <= d_minus_c when '0', c_minus_d when others; with sign select cd <= c when '0', d when others; half_b <= '0' & b(K-1 downto 1); with sel select next_a <= p when "00", a when "01", ab when others; with sel select next_b <= y when "00", half_b when "01", ba_minus_ab when others; with sel select next_c <= ZERO when "00", c when "01", cd when others; with sel select next_d <= x when "00", half_d when "01", dc_minus_cd when others; a_equal_1 <= '1' when a = ONE else '0'; b_0 <= b(0); z <= c; parallel_registers: process(clk) begin if clk'event and clk = '1' then if ce = '1' then a <= next_a; b <= next_b; c <= next_c; d <= next_d; end if; end if; end process parallel_registers; control_unit: process(clk, reset, current_state, a_equal_1, b_0) begin case current_state is when 0 to 1 => ce <= '0'; sel <= "00"; done <= '1'; when 2 => ce <= '1'; sel <= "00"; done <= '0'; when 3 => if a_equal_1 = '1' then ce <= '0'; sel <= "00"; elsif b_0 = '0' then ce <= '1'; sel <= "01"; else ce <= '1'; sel <= "10"; end if; 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 a_equal_1 = '1' then current_state <= 0; end if; end case; end if; end process; end rtl;