----------------------------------------------------------------------------
-- Montgomery Multiplier (montgomey_mult.vhd)
--
--
--
-- Computes the polynomial multiplication x.y.r^-1 mod f in GF(2**m)
-- Implements a sequential cincuit
-- Defines 2 entities (montg_cell and montgomery_mult)
--
----------------------------------------------------------------------------
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use IEEE.std_logic_unsigned.all;
package montgomery_mult_package is
constant M: integer := 8;
constant F: std_logic_vector(M-1 downto 0):= "00011011"; --for M=8 bits
--constant F: std_logic_vector(M-1 downto 0):= x"001B"; --for M=16 bits
--constant F: std_logic_vector(M-1 downto 0):= x"0101001B"; --for M=32 bits
--constant F: std_logic_vector(M-1 downto 0):= x"010100000101001B"; --for M=64 bits
--constant F: std_logic_vector(M-1 downto 0):= x"0000000000000000010100000101001B"; --for M=128 bits
--constant F: std_logic_vector(M-1 downto 0):= "000"&x"00000000000000000000000000000000000000C9"; --for M=163
--constant F: std_logic_vector(M-1 downto 0):= (0=> '1', 74 => '1', others => '0'); --for M=233
--constant F: std_logic_vector(M-1 downto 0):= (others => '1'); --for M=233
end montgomery_mult_package;
-----------------------------------
-- Montgomery multiplier basic data_path
-----------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
use work.montgomery_mult_package.all;
entity montg_cell is
port (
c: in std_logic_vector(M-1 downto 0);
b: in std_logic_vector(M-1 downto 0);
a_i: in std_logic;
new_c: out std_logic_vector(M-1 downto 0)
);
end montg_cell;
architecture rtl of montg_cell is
signal prev_c0: std_logic;
begin
prev_c0 <= c(0) xor (a_i and b(0));
datapath: for i in 1 to M-1 generate
new_c(i-1) <= c(i) xor (a_i and b(i)) xor (F(i) and prev_c0);
end generate;
new_c(M-1) <= prev_c0;
end rtl;
-----------------------------------
-- Montgomery multiplier
-----------------------------------
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use IEEE.std_logic_unsigned.all;
use work.montgomery_mult_package.all;
entity montgomery_mult is
port (
a, b: 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 montgomery_mult;
architecture rtl of montgomery_mult is
component montg_cell is
port (
C: in std_logic_vector(M-1 downto 0);
B: in std_logic_vector(M-1 downto 0);
a_i: in std_logic;
new_c: out std_logic_vector(M-1 downto 0)
);
end component montg_cell;
signal inic, shift_r, ce_c: std_logic;
signal count: natural range 0 to M;
type states is range 0 to 3;
signal current_state: states;
signal aa, bb, cc, new_c: std_logic_vector (M-1 downto 0);
begin
data_path: montg_cell port map (C => cc, B => bb, a_i => aa(0), new_c => new_c);
counter: process(reset, clk)
begin
if reset = '1' then count <= 0;
elsif clk' event and clk = '1' then
if inic = '1' then
count <= 0;
elsif shift_r = '1' then
count <= count+1;
end if;
end if;
end process counter;
sh_register_A: process(clk) --Shift register A
begin
if reset = '1' then
aa <= (others => '0');
elsif clk'event and clk = '1' then
if inic = '1' then
aa <= a;
else
aa <= '0' & aa(M-1 downto 1);
end if;
end if;
end process sh_register_A;
register_B: process(clk)
begin
if reset = '1' then
bb <= (others => '0');
elsif clk'event and clk = '1' then
if inic = '1' then
bb <= b;
end if;
end if;
end process register_B;
register_C: process(inic, clk)
begin
if inic = '1' or reset = '1' then
cc <= (others => '0');
elsif clk'event and clk = '1' then
if ce_c = '1' then
cc <= new_c;
end if;
end if;
end process register_C;
z <= cc;
control_unit: process(clk, reset, current_state)
begin
case current_state is
when 0 to 1 => inic <= '0'; shift_r <= '0'; done <= '1'; ce_c <= '0';
when 2 => inic <= '1'; shift_r <= '0'; done <= '0'; ce_c <= '0';
when 3 => inic <= '0'; shift_r <= '1'; done <= '0'; ce_c <= '1';
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 count = M-1 then current_state <= 0; end if;
end case;
end if;
end process control_unit;
end rtl;