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_point_multiplication is port ( xP, yP, k: in std_logic_vector(m-1 downto 0); clk, reset, start: in std_logic; xQ, yQ: out std_logic_vector(m-1 downto 0); Q_infinity, done: out std_logic ); end Montgomery_point_multiplication; architecture circuit of Montgomery_point_multiplication is component 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 component; signal xA, xB, next_A, next_B, xQ_in, mont_ad, xPxoryP, int_k, xAxorxB: std_logic_vector(m-1 downto 0); signal sel_AB, sel_in, sel_Q, ce_A, ce_B, A_infinity, B_infinity, k_m_minus_1, mont_start, mont_done, reset_counter, count_down, last_step, condition: std_logic; signal mont_operation: std_logic_vector(1 downto 0); signal step_number: std_logic_vector(logm-1 downto 0); constant zero: std_logic_vector(m-1 downto 0) := (others => '0'); subtype states is natural range 0 to 26; signal current_state: states; begin with sel_in select xQ_in <= xA when '0', xB when others; with sel_AB select next_A <= mont_ad when '1', xB when others; with sel_AB select next_B <= xP when '0', mont_ad when others; with sel_Q select xQ <= xP when '1', xA when others; with sel_Q select yQ <= xPxoryP when '1', mont_ad when others; main_component: Montgomery_addition_doubling port map(xA, xB, xQ_in, xP, yP, clk, reset, mont_start, mont_operation, mont_ad, mont_done); xor_gates: for i in 0 to m-1 generate xPxoryP(i) <= xP(i) xor yP(i); xAxorxB(i) <= xA(i) xor xB(i); end generate; long_nor: process(xAxorxB) begin if xAxorxB = zero then condition <= '1'; else condition <= '0'; end if; end process; counter: process(clk) begin if clk' event and clk = '1' then if reset_counter = '1' then step_number <= conv_std_logic_vector(m, logm); elsif count_down = '1' then step_number <= step_number - 1; end if; end if; end process; with step_number select last_step <= '1' when "00000000", '0' when others; shift_register: process(clk) begin if clk'event and clk = '1' then if reset_counter = '1' then int_k <= k; elsif count_down = '1' then for i in m-1 downto 1 loop int_k(i) <= int_k(i-1); end loop; int_k(0) <= '0'; end if; end if; end process; k_m_minus_1 <= int_k(m-1); register_A: process(clk) begin if clk' event and clk = '1' then if ce_A = '1' then xA <= next_A; end if; end if; end process; register_B: process(clk) begin if clk' event and clk = '1' then if ce_B = '1' then xB <= next_B; end if; end if; end process; Q_infinity <= A_infinity; control_unit: process(clk, reset, current_state) begin case current_state is when 0 to 1 => sel_AB <= '0'; ce_A <= '0'; ce_B <= '0'; sel_in <= '0'; mont_start <= '0'; reset_counter <= '0'; count_down <= '0'; done <= '1'; when 2 => sel_AB <= '0'; ce_A <= '0'; ce_B <= '1'; sel_in <= '0'; mont_start <= '0'; reset_counter <= '1'; count_down <= '0'; done <= '0'; A_infinity <= '1'; B_infinity <= '0'; when 3 to 5 => sel_AB <= '0'; ce_A <= '0'; ce_B <= '0'; sel_in <= '0'; mont_start <= '0'; reset_counter <= '0'; count_down <= '0'; done <= '0'; when 6 => sel_AB <= '0'; ce_A <= '0'; ce_B <= '0'; sel_in <= '0'; mont_operation <= "00"; mont_start <= '1'; reset_counter <= '0'; count_down <= '0'; done <= '0'; when 7 => sel_AB <= '0'; ce_A <= '0'; ce_B <= '0'; sel_in <= '0'; mont_start <= '0'; reset_counter <= '0'; count_down <= '0'; done <= '0'; when 8 => sel_AB <= '1'; ce_A <= '0'; ce_B <= '1'; sel_in <= '0'; mont_start <= '0'; reset_counter <= '0'; count_down <= '0'; done <= '0'; when 9 => sel_AB <= '0'; ce_A <= '0'; ce_B <= '0'; sel_in <= '0'; mont_operation <= "01"; mont_start <= '1'; reset_counter <= '0'; count_down <= '0'; done <= '0'; when 10 => sel_AB <= '0'; ce_A <= '0'; ce_B <= '0'; sel_in <= '0'; mont_start <= '0'; reset_counter <= '0'; count_down <= '0'; done <= '0'; when 11 => sel_AB <= '1'; ce_A <= '1'; ce_B <= '0'; sel_in <= '0'; mont_start <= '0'; reset_counter <= '0'; count_down <= '0'; done <= '0'; when 12 => sel_AB <= '0'; ce_A <= '0'; ce_B <= '0'; sel_in <= '0'; mont_start <= '0'; reset_counter <= '0'; count_down <= '0'; done <= '0'; when 13 => sel_AB <= '0'; ce_A <= '0'; ce_B <= '0'; sel_in <= '0'; mont_operation <= "00"; mont_start <= '1'; reset_counter <= '0'; count_down <= '0'; done <= '0'; when 14 => sel_AB <= '0'; ce_A <= '0'; ce_B <= '0'; sel_in <= '0'; mont_start <= '0'; reset_counter <= '0'; count_down <= '0'; done <= '0'; when 15 => sel_AB <= '1'; ce_A <= '1'; ce_B <= '0'; sel_in <= '0'; mont_start <= '0'; reset_counter <= '0'; count_down <= '0'; done <= '0'; when 16 => sel_AB <= '0'; ce_A <= '0'; ce_B <= '0'; sel_in <= '1'; mont_operation <= "01"; mont_start <= '1'; reset_counter <= '0'; count_down <= '0'; done <= '0'; when 17 => sel_AB <= '0'; ce_A <= '0'; ce_B <= '0'; sel_in <= '1'; mont_start <= '0'; reset_counter <= '0'; count_down <= '0'; done <= '0'; when 18 => sel_AB <= '1'; ce_A <= '0'; ce_B <= '1'; sel_in <= '1'; mont_start <= '0'; reset_counter <= '0'; count_down <= '0'; done <= '0'; when 19 => sel_AB <= '0'; ce_A <= '0'; ce_B <= '0'; sel_in <= '0'; mont_start <= '0'; reset_counter <= '0'; count_down <= '0'; done <= '0'; B_infinity <= '1'; when 20 => sel_AB <= '0'; ce_A <= '1'; ce_B <= '0'; sel_in <= '0'; mont_start <= '0'; reset_counter <= '0'; count_down <= '0'; done <= '0'; A_infinity <= '0'; when 21 => sel_AB <= '0'; ce_A <= '0'; ce_B <= '0'; sel_in <= '0'; mont_start <= '0'; reset_counter <= '0'; count_down <= '1'; done <= '0'; when 22 => sel_AB <= '0'; ce_A <= '0'; ce_B <= '0'; sel_in <= '0'; mont_start <= '0'; reset_counter <= '0'; count_down <= '0'; done <= '0'; when 23 => sel_AB <= '0'; ce_A <= '0'; ce_B <= '0'; sel_in <= '0'; mont_start <= '0'; reset_counter <= '0'; count_down <= '0'; done <= '0'; when 24 => sel_AB <= '0'; ce_A <= '0'; ce_B <= '0'; sel_in <= '0'; mont_operation <= "10"; mont_start <= '1'; reset_counter <= '0'; count_down <= '0'; done <= '0'; when 25 => sel_AB <= '0'; ce_A <= '0'; ce_B <= '0'; sel_in <= '0'; sel_Q <= '0'; mont_start <= '0'; reset_counter <= '0'; count_down <= '0'; done <= '0'; when 26 => sel_AB <= '0'; ce_A <= '0'; ce_B <= '0'; sel_in <= '0'; sel_Q <= '1'; mont_start <= '0'; reset_counter <= '0'; count_down <= '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 k_m_minus_1 = '0' then current_state <= 4; else current_state <= 12; end if; when 4 => if A_infinity = '0' then current_state <= 5; else current_state <= 21; end if; when 5 => if condition = '0' then current_state <= 6; else current_state <= 19; end if; when 6 => current_state <= 7; when 7 => if mont_done = '1' then current_state <= 8; end if; when 8 => current_state <= 9; when 9 => current_state <= 10; when 10 => if mont_done = '1' then current_state <= 11; end if; when 11 => current_state <= 21; when 12 => if A_infinity = '0' then current_state <= 13; else current_state <= 20; end if; when 13 => current_state <= 14; when 14 => if mont_done = '1' then current_state <= 15; end if; when 15 => current_state <= 16; when 16 => current_state <= 17; when 17 => if mont_done = '1' then current_state <= 18; end if; when 18 => current_state <= 21; when 19 => current_state <= 9; when 20 => current_state <= 16; when 21 => current_state <= 22; when 22 => if last_step = '1' then current_state <= 23; else current_state <= 3; end if; when 23 => if B_infinity = '1' then current_state <= 26; else current_state <= 24; end if; when 24 => current_state <= 25; when 25 => if mont_done = '1' then current_state <= 0; end if; when 26 => current_state <= 0; end case; end if; end process; end circuit;