library IEEE; use IEEE.std_logic_1164.all; use IEEE.std_logic_arith.all; use IEEE.std_logic_unsigned.all; use work.my_package.all; entity Montgomery_addition_doubling is port( xA, xB, xQ, xP, yP: in std_logic_vector(m-1 downto 0); clk, reset, start: in std_logic; operation: std_logic_vector(1 downto 0); xyR: out std_logic_vector(m-1 downto 0); done: out std_logic ); end Montgomery_addition_doubling; architecture circuit of Montgomery_addition_doubling is component multiplier_163_7_6_3 is port ( a, b: in std_logic_vector(m-1 downto 0); clk, reset, start: in std_logic; c: inout std_logic_vector(m-1 downto 0); done: out std_logic ); end component; component divider_163_7_6_3 is port( g, h: in std_logic_vector(m-1 downto 0); clk, reset, start: in std_logic; z: out std_logic_vector(m-1 downto 0); done: out std_logic ); end component; component square_163_7_6_3 is port ( a: in std_logic_vector(162 downto 0); z: out std_logic_vector(162 downto 0) ); end component; signal mult_in1, mult_in2, product, squareP, acc_in, acc_out, div_in1, div_in2, squareQ, quotient, square_quotient, funct1, funct2: std_logic_vector(m-1 downto 0); signal sel, start_mult, mult_done, ce_acc, start_div, div_done: std_logic; subtype state is natural range 0 to 11; signal current_state: state; begin gates1: for i in 0 to m-1 generate mult_in1(i) <= xA(i) xor xP(i); mult_in2(i) <= (not(sel) and (xB(i) xor xP(i))) or (sel and acc_out(i)); end generate; multiplier: multiplier_163_7_6_3 port map(mult_in1, mult_in2, clk, reset, start_mult, product, mult_done); square1: square_163_7_6_3 port map(xP, squareP); gates2: for i in 0 to m-1 generate acc_in(i) <= yP(i) xor product(i) xor squareP(i); end generate; accumulator: process(clk) begin if clk'event and clk = '1' then if ce_acc = '1' then acc_out <= acc_in; end if; end if; end process accumulator; gates3: for i in 1 to m-1 generate div_in1(i) <= (not(operation(1)) and not(operation(0)) and xB(i)) or (operation(1) and product(i)); end generate; div_in1(0) <= (not(operation(1)) and not(operation(0)) and xB(0)) or (not(operation(1)) and operation(0)) or (operation(1) and product(0)); gates4: for i in 0 to m-1 generate funct1(i) <= not(operation(1)) and ((not(operation(0)) and (xA(i) xor xB(i))) or (operation(0) and squareQ(i))); div_in2(i) <= funct1(i) or (operation(1) and xP(i)); funct2(i) <= not(operation(1)) and ( quotient(i) xor ((not(operation(0)) and (xP(i) xor square_quotient(i)))) xor ((operation(0) and squareQ(i)))); xyR(i) <= funct2(i) or (operation(1) and (quotient(i) xor yP(i))); end generate; square2: square_163_7_6_3 port map(xQ, squareQ); square3: square_163_7_6_3 port map(quotient, square_quotient); divider: divider_163_7_6_3 port map(div_in1, div_in2, clk, reset, start_div, quotient, div_done); control_unit: process(clk, reset, current_state) begin case current_state is when 0 => sel <= '0'; start_mult <= '0'; start_div <= '0'; ce_acc <= '0'; done <= '1'; when 1 => sel <= '0'; start_mult <= '0'; start_div <= '0'; ce_acc <= '0'; done <= '1'; when 2 => sel <= '0'; start_mult <= '0'; start_div <= '0'; ce_acc <= '0'; done <= '0'; when 3 => sel <= '0'; start_mult <= '0'; start_div <= '1'; ce_acc <= '0'; done <= '0'; when 4 => sel <= '0'; start_mult <= '0'; start_div <= '0'; ce_acc <= '0'; done <= '0'; when 5 => sel <= '0'; start_mult <= '1'; start_div <= '0'; ce_acc <= '0'; done <= '0'; when 6 => sel <= '0'; start_mult <= '0'; start_div <= '0'; ce_acc <= '0'; done <= '0'; when 7 => sel <= '0'; start_mult <= '0'; start_div <= '0'; ce_acc <= '1'; done <= '0'; when 8 => sel <= '1'; start_mult <= '1'; start_div <= '0'; ce_acc <= '0'; done <= '0'; when 9 => sel <= '1'; start_mult <= '0'; start_div <= '0'; ce_acc <= '0'; done <= '0'; when 10 => sel <= '1'; start_mult <= '0'; start_div <= '1'; ce_acc <= '0'; done <= '0'; when 11 => sel <= '1'; start_mult <= '0'; start_div <= '0'; ce_acc <= '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 => if operation(1) = '0' then current_state <= 3; else current_state <= 5; end if; --start division when 3 => current_state <= 4; --wait for division when 4 => if div_done = '1' then current_state <= 0; end if; --start first multiplication when 5 => current_state <= 6; --wait for multiplication when 6 => if mult_done = '1' then current_state <= 7; end if; --update accumulator when 7 => current_state <= 8; --start second multiplication when 8 => current_state <= 9; --wait for multiplication when 9 => if mult_done = '1' then current_state <= 10; end if; --start division when 10 => current_state <= 11; --wait for division when 11 => if div_done = '1' then current_state <= 0; end if; end case; end if; end process; end circuit;