--library IEEE; --use IEEE.std_logic_1164.all; --use IEEE.std_logic_arith.all; --use IEEE.std_logic_unsigned.all; --package my_package is --constant m: natural := 163; --constant logm: natural := 8; --constant zero: std_logic_vector(m-1 downto 0) := (others => '0'); --end my_package; 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 Frobenius_point_multiplication is port ( xP, yP, k: in std_logic_vector(m-1 downto 0); clk, reset, start: in std_logic; xQ, yQ: inout std_logic_vector(m-1 downto 0); done: out std_logic ); end Frobenius_point_multiplication; architecture circuit of Frobenius_point_multiplication is constant zero: std_logic_vector(m-1 downto 0) := (others => '0'); component EC_addition_doubling is port( xP, yP, xQ, yQ: in std_logic_vector(m-1 downto 0); clk, reset, start, addition: in std_logic; xR: inout std_logic_vector(m-1 downto 0); yR: out std_logic_vector(m-1 downto 0); done: out std_logic ); end component; component square_163_7_6_3 port ( a: in std_logic_vector(162 downto 0); z: out std_logic_vector(162 downto 0) ); end component; signal a, not_a, updated_a, next_a: std_logic_vector(m downto 0); signal b, updated_b, next_b: std_logic_vector(m-1 downto 0); signal carry_a, carry_b: std_logic; signal xxP, yyP, xR, yR, add, next_xxP, next_yyP, next_xQ, next_yQ, operand_yP, xxPxorxQ, yyPxoryQ, yyPxoryQxorxxP, square_x, square_y: std_logic_vector(m-1 downto 0); signal ce_P, ce_Q, ce_AB, sel_P, sel_ab, sel_operand, addition, operation, start_operation, operation_done, xQequalxP, yQequalyP, QequalP, yQequalMinusyP, QequalMinusP, endOfLoop, Q_infinity, aEqualZero, bEqualZero, op, sop: std_logic; signal sel_Q: std_logic_vector(1 downto 0); subtype states is natural range 0 to 22; signal current_state: states; begin with sel_P select next_xxP <= xP when '0', square_x when others; with sel_P select next_yyP <= yP when '0', square_y when others; with sel_Q select next_xQ <= xxP when "00", xxP when "01", xR when others; with sel_Q select next_yQ <= yyP when "00", add when "01", yR when others; with sel_ab select next_a <= ('0'&k) when '0', updated_a when others; with sel_ab select next_b <= zero when '0', updated_b when others; condition_generation: for i in 0 to m-1 generate xxPxorxQ(i) <= xxP(i) xor xQ(i); yyPxoryQ(i) <= yyP(i) xor yQ(i); yyPxoryQxorxxP(i) <= yyPxoryQ(i) xor xxP(i); end generate; long_nors: process(xxPxorxQ, yyPxoryQ, yyPxoryQxorxxP, a, b) begin if xxPxorxQ = zero then xQequalxP <= '1'; else xQequalxP <= '0'; end if; if yyPxoryQ = zero then yQequalyP <= '1'; else yQequalyP <= '0'; end if; if yyPxoryQxorxxP = zero then yQequalMinusyP <= '1'; else yQequalMinusyP <= '0'; end if; if a(m-1 downto 0) = zero then aEqualZero <= '1'; else aEqualZero <= '0'; end if; if b = zero then bEqualZero <= '1'; else bEqualZero <= '0'; end if; end process long_nors; QequalP <= xQequalxP and yQequalyP; QequalMinusP <= xQequalxP and yQequalMinusyP; endOfLoop <= aEqualZero and bEqualZero; register_P: process(clk) begin if clk' event and clk = '1' then if ce_P = '1' then xxP <= next_xxP; yyP <= next_yyP; end if; end if; end process; register_Q: process(clk) begin if clk' event and clk = '1' then if ce_Q = '1' then xQ <= next_xQ; yQ <= next_yQ; end if; end if; end process; register_AB: process(clk) begin if clk' event and clk = '1' then if ce_AB = '1' then a <= next_a; b <= next_b; end if; end if; end process; with sel_operand select operand_yP <= yyP when '0', add when others; addition <= not(operation); main_component: EC_addition_doubling port map(xxP, operand_yP, xQ, yQ, clk, reset, start_operation, addition, xR, yR, operation_done); xor_gates: for i in 0 to m-1 generate add(i) <= xxP(i) xor yyP(i); end generate; carry_b <= not(carry_a); --update_block: for i in 0 to m-2 generate --updated_a(i) <= (a(i+1) xor b(i)) xor carry_a(i); --carry_a(i+1) <= (a(i+1) and b(i)) or (a(i+1) and carry_a(i)) or (b(i) and carry_a(i)); --updated_b(i) <= not(a(i+1)) xor carry_b(i); --carry_b(i+1) <= not(a(i+1)) and carry_b(i); --end generate; --updated_a(m-1) <= (a(m) xor b(m-1)) xor carry_a(m-1); --carry_a(m) <= (a(m) and b(m-1)) or (a(m) and carry_a(m-1)) or (b(m-1) and carry_a(m-1)); --updated_a(m) <= (a(m) xor b(m-1)) xor carry_a(m); --updated_b(m-1) <= not(a(m)) xor carry_b(m-1); updated_a <= (b(m-1)&b) + (a(m)&a(m downto 1)) + carry_a; nor_gates: for i in 0 to m generate not_a(i) <= not(a(i)); end generate; updated_b <= not_a(m downto 1) + carry_b; square_block1: square_163_7_6_3 port map(xxP, square_x); square_block2: square_163_7_6_3 port map(yyP, square_y); control_unit: process(clk, reset, current_state) begin case current_state is when 0 to 1 => ce_P <= '0'; ce_Q <= '0'; ce_AB <= '0'; sel_P <= '0'; sel_Q <= "00"; sel_AB <= '0'; sel_operand <= '0'; done <= '1'; when 2 => ce_P <= '1'; ce_Q <= '0'; ce_AB <= '1'; sel_P <= '0'; sel_Q <= "00"; sel_AB <= '0'; sel_operand <= '0'; done <= '0'; Q_infinity <= '1'; when 3 => ce_P <= '0'; ce_Q <= '0'; ce_AB <= '0'; sel_P <= '0'; sel_Q <= "00"; sel_AB <= '0'; sel_operand <= '0'; done <= '0'; when 4 => ce_P <= '0'; ce_Q <= '0'; ce_AB <= '0'; sel_P <= '0'; sel_Q <= "00"; sel_AB <= '0'; sel_operand <= '0'; done <= '0'; carry_a <= '0'; when 5 => ce_P <= '0'; ce_Q <= '0'; ce_AB <= '0'; sel_P <= '0'; sel_Q <= "00"; sel_AB <= '0'; sel_operand <= '0'; done <= '0'; carry_a <= '0'; when 6 => ce_P <= '0'; ce_Q <= '1'; ce_AB <= '0'; sel_P <= '0'; sel_Q <= "00"; sel_AB <= '0'; sel_operand <= '0'; done <= '0'; Q_infinity <= '0'; when 7 => ce_P <= '0'; ce_Q <= '0'; ce_AB <= '0'; sel_P <= '0'; sel_Q <= "00"; sel_AB <= '0'; sel_operand <= '0'; done <= '0'; when 8 => ce_P <= '0'; ce_Q <= '0'; ce_AB <= '0'; sel_P <= '0'; sel_Q <= "00"; sel_AB <= '0'; sel_operand <= '0'; done <= '0'; when 9 => ce_P <= '0'; ce_Q <= '1'; ce_AB <= '0'; sel_P <= '0'; sel_Q <= "10"; sel_AB <= '0'; sel_operand <= '0'; done <= '0'; when 10 => ce_P <= '0'; ce_Q <= '0'; ce_AB <= '0'; sel_P <= '0'; sel_Q <= "00"; sel_AB <= '0'; sel_operand <= '0'; done <= '0'; when 11 => ce_P <= '0'; ce_Q <= '0'; ce_AB <= '0'; sel_P <= '0'; sel_Q <= "00"; sel_AB <= '0'; sel_operand <= '0'; done <= '0'; when 12 => ce_P <= '0'; ce_Q <= '1'; ce_AB <= '0'; sel_P <= '0'; sel_Q <= "10"; sel_AB <= '0'; sel_operand <= '0'; done <= '0'; when 13 => ce_P <= '0'; ce_Q <= '0'; ce_AB <= '0'; sel_P <= '0'; sel_Q <= "00"; sel_AB <= '0'; sel_operand <= '0'; done <= '0'; carry_a <= '1'; when 14 => ce_P <= '0'; ce_Q <= '1'; ce_AB <= '0'; sel_P <= '0'; sel_Q <= "01"; sel_AB <= '0'; sel_operand <= '0'; done <= '0'; Q_infinity <= '0'; when 15 => ce_P <= '0'; ce_Q <= '0'; ce_AB <= '0'; sel_P <= '0'; sel_Q <= "00"; sel_AB <= '0'; sel_operand <= '1'; done <= '0'; when 16 => ce_P <= '0'; ce_Q <= '0'; ce_AB <= '0'; sel_P <= '0'; sel_Q <= "00"; sel_AB <= '0'; sel_operand <= '1'; done <= '0'; when 17 => ce_P <= '0'; ce_Q <= '1'; ce_AB <= '0'; sel_P <= '0'; sel_Q <= "10"; sel_AB <= '0'; sel_operand <= '1'; done <= '0'; when 18 => ce_P <= '0'; ce_Q <= '0'; ce_AB <= '0'; sel_P <= '0'; sel_Q <= "00"; sel_AB <= '0'; sel_operand <= '1'; done <= '0'; when 19 => ce_P <= '0'; ce_Q <= '0'; ce_AB <= '0'; sel_P <= '0'; sel_Q <= "00"; sel_AB <= '0'; sel_operand <= '1'; done <= '0'; when 20 => ce_P <= '0'; ce_Q <= '1'; ce_AB <= '0'; sel_P <= '0'; sel_Q <= "10"; sel_AB <= '0'; sel_operand <= '1'; done <= '0'; when 21 => ce_P <= '1'; ce_Q <= '0'; ce_AB <= '1'; sel_P <= '1'; sel_Q <= "00"; sel_AB <= '1'; sel_operand <= '0'; done <= '0'; when 22 => ce_P <= '0'; ce_Q <= '0'; ce_AB <= '0'; sel_P <= '0'; sel_Q <= "00"; sel_AB <= '0'; sel_operand <= '0'; done <= '0'; end case; --when 7 => --when 8 => --when 9 => --when 10 => --when 15 => --when 16 => --when 17 => --when 18 => operation <= op; start_operation <= sop; 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; op<='0'; sop<='0'; end if; when 1 => if start = '1' then current_state <= 2; op<='0'; sop<='0'; end if; when 2 => current_state <= 3; op<='0'; sop<='0'; when 3 => if a(0) = '0' then current_state <= 4; op<='0'; sop<='0'; elsif a(1) = b(0) then current_state <= 5; op<='0'; sop<='0'; else current_state <= 13; op<='0'; sop<='0'; end if; when 4 => current_state <= 21; op<='0'; sop<='0'; when 5 => if Q_infinity = '1' then current_state <= 6; op<='0'; sop<='0'; elsif QequalP = '1' then current_state <= 7; op<='1'; sop<='1'; -- else current_state <= 10; op<='0'; sop<='1'; end if; when 6 => current_state <= 21; op<='0'; sop<='0'; when 7 => current_state <= 8; op<='1'; sop<='0'; -- when 8 => if operation_done = '1' then current_state <= 9; op<='1'; sop<='0'; end if; when 9 => current_state <= 21; op<='0'; sop<='0'; when 10 => current_state <= 11; op<='0'; sop<='0'; when 11 => if operation_done = '1' then current_state <= 12; op<='0'; sop<='0'; end if; when 12 => current_state <= 21; op<='0'; sop<='0'; when 13 => if Q_infinity = '1' then current_state <= 14; op<='0'; sop<='0'; elsif QequalMinusP = '1' then current_state <= 15; op<='1'; sop<='1'; -- else current_state <= 18; op<='0'; sop<='1'; end if; -- when 14 => current_state <= 21; op<='0'; sop<='0'; when 15 => current_state <= 16; op<='1'; sop<='0'; -- when 16 => if operation_done = '1' then current_state <= 17; op<='1'; sop<='0'; end if; -- when 17 => current_state <= 21; op<='0'; sop<='0'; when 18 => current_state <= 19; op<='0'; sop<='0'; when 19 => if operation_done = '1' then current_state <= 20; op<='0'; sop<='0'; end if; when 20 => current_state <= 21; op<='0'; sop<='0'; when 21 => current_state <= 22; op<='0'; sop<='0'; when 22 => if endOfLoop = '1' then current_state <= 0; else current_state <= 3; op<='0'; sop<='0'; end if; end case; end if; end process; end circuit;