Q: Efficient modular arithmetic in VHDL

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;







up vote
1
down vote

favorite












I'm building some modules in VHDL for handling modular arithmetic and want to make sure it's well-designed for timing and somewhat efficient when scaling up. This will need to work with 128-bit or 256-bit arithmetic when complete, but I'm testing it currently with small 16-bit numbers currently. There are two modules, mod_add for the basic modular arithmetic, and mod_mul for the multiplication built on top of modular addition.



library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity mod_add is
generic(
bits : positive := 16;
modulo : positive := 15
);
port(
clk : in std_logic;
rst : in std_logic;
a : in std_logic_vector(bits-1 downto 0);
b : in std_logic_vector(bits-1 downto 0);
q : out std_logic_vector(bits-1 downto 0) := (others => '0')
);
end entity;

architecture behavior of mod_add is
constant modulo_c : std_logic_vector(bits-1 downto 0) := std_logic_vector(to_unsigned(modulo, bits));
signal q_int : std_logic_vector(bits downto 0) := (others => '0');
signal q_out : std_logic_vector(bits downto 0) := (others => '0');
begin
process(clk)
begin
if rising_edge(clk) then
if rst = '1' then
q_int <= (others => '0');
q_out <= (others => '0');
else
q_int <= std_logic_vector(unsigned("0" & a) + unsigned("0" & b));
if unsigned(q_int) >= unsigned("0" & modulo_c) then
q_out <= std_logic_vector(unsigned(q_int) - unsigned(modulo_c));
else
q_out <= q_int;
end if;
end if;
end if;
end process;

q <= q_out(bits-1 downto 0);
end architecture behavior;

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity mod_mul is
generic(
bits : positive := 16;
modulo : positive := 15
);
port(
clk : in std_logic;
rst : in std_logic;
load : in std_logic;
ready : out std_logic := '0';
a : in std_logic_vector(bits-1 downto 0);
b : in std_logic_vector(bits-1 downto 0);
q : out std_logic_vector(bits-1 downto 0) := (others => '0')
);
end entity;

architecture behavior of mod_mul is
component mod_add
generic(
bits : positive := 16;
modulo : positive := 15
);
port(
clk : in std_logic;
rst : in std_logic;
a : in std_logic_vector(bits-1 downto 0);
b : in std_logic_vector(bits-1 downto 0);
q : out std_logic_vector(bits-1 downto 0)
);
end component mod_add;

constant p_c : std_logic_vector(bits-1 downto 0) := std_logic_vector(to_unsigned(modulo, bits));
signal q_int : std_logic_vector(bits downto 0) := (others => '0');
signal q_out : std_logic_vector(bits downto 0) := (others => '0');

constant b_zero : std_logic_vector(bits-1 downto 0) := (others => '0');
signal b_shift : std_logic_vector(bits-1 downto 0) := (others => '0');
signal culm : std_logic_vector(bits-1 downto 0) := (others => '0');
signal val : std_logic_vector(bits-1 downto 0) := (others => '0');
signal culm_add_val : std_logic_vector(bits-1 downto 0) := (others => '0');
signal val_double : std_logic_vector(bits-1 downto 0) := (others => '0');
signal counter : std_logic_vector(1 downto 0) := "00";
begin
culm_add_val_proc: mod_add generic map(
bits => bits,
modulo => modulo
) port map(
clk => clk,
rst => rst,
a => culm,
b => val,
q => culm_add_val
);

val_double_proc: mod_add generic map(
bits => bits,
modulo => modulo
) port map(
clk => clk,
rst => rst,
a => val,
b => val,
q => val_double
);

process(clk)
begin
if rising_edge(clk) then
if rst = '1' then
counter <= (others => '0');
elsif load = '1' then
counter <= (others => '0');
else
counter <= std_logic_vector(unsigned(counter) + 1);
end if;
end if;
end process;

process(clk)
begin
if rising_edge(clk) then
if rst = '1' then
culm <= (others => '0');
val <= (others => '0');
elsif load = '1' then
culm <= (others => '0');
val <= a;
b_shift <= b;
elsif counter = "10" then
if b_shift(0) = '1' then
culm <= culm_add_val;
end if;
val <= val_double;
b_shift <= "0" & b_shift(bits-1 downto 1);
end if;
end if;
end process;

q <= culm;
ready <= '1' when b_shift = b_zero else '0';
end architecture behavior;


And the test bench for mod_mul:



library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity test_mod_mul is
end entity test_mod_mul;

architecture behavioral of test_mod_mul is
component mod_mul
generic(
bits : positive := 16;
modulo : positive := 15
);
port(
clk : in std_logic;
rst : in std_logic;
load : in std_logic;
ready : out std_logic;
a : in std_logic_vector(bits-1 downto 0);
b : in std_logic_vector(bits-1 downto 0);
q : out std_logic_vector(bits-1 downto 0)
);
end component mod_mul;

constant clk_period : time := 20 ns;
signal halt : boolean := false;

signal clk : std_logic := '0';
signal rst : std_logic := '0';
signal load : std_logic := '0';
signal a, b : std_logic_vector(15 downto 0);
signal a_in, b_in : integer := 0;

signal ready : std_logic;
signal q : std_logic_vector(15 downto 0);
signal q_out : integer;
begin
uut: mod_mul port map(
clk => clk,
rst => rst,
load => load,
ready => ready,
a => a,
b => b,
q => q
);

a <= std_logic_vector(to_unsigned(a_in, a'length));
b <= std_logic_vector(to_unsigned(b_in, b'length));
q_out <= to_integer(unsigned(q));

process
begin
clk <= '1';
wait for clk_period/2;
clk <= '0';
wait for clk_period/2;
if halt then
wait;
end if;
end process;

process
procedure check_multiply(
constant a, b : in integer;
constant q : in integer) is
begin
wait until falling_edge(clk);
a_in <= a;
b_in <= b;
load <= '1';
wait for clk_period;
load <= '0';
wait until rising_edge(clk) and ready = '1';
assert q_out = q report "Failed mod multiplication" severity error;
end procedure check_multiply;
begin
rst <= '1';
wait for 10*clk_period;
rst <= '0';
wait for clk_period;
assert ready = '1' report "Not ready" severity error;
assert q_out = 0 report "Failed mod multiplication" severity failure;

check_multiply(2, 2, 4);
check_multiply(2, 3, 6);
check_multiply(3, 3, 9);
check_multiply(4, 4, 1);
check_multiply(6, 5, 0);
check_multiply(6, 7, 12);

wait for 1000 ns;
halt <= true;
wait;
end process;
end architecture behavioral;






share|improve this question



















  • Can I ask what you are designing? ASIC? FPGA? What synthesis tools are you using? What arithmetic functions do you want to realize (in equations)?
    – JHBonarius
    Jun 26 at 19:46

















up vote
1
down vote

favorite












I'm building some modules in VHDL for handling modular arithmetic and want to make sure it's well-designed for timing and somewhat efficient when scaling up. This will need to work with 128-bit or 256-bit arithmetic when complete, but I'm testing it currently with small 16-bit numbers currently. There are two modules, mod_add for the basic modular arithmetic, and mod_mul for the multiplication built on top of modular addition.



library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity mod_add is
generic(
bits : positive := 16;
modulo : positive := 15
);
port(
clk : in std_logic;
rst : in std_logic;
a : in std_logic_vector(bits-1 downto 0);
b : in std_logic_vector(bits-1 downto 0);
q : out std_logic_vector(bits-1 downto 0) := (others => '0')
);
end entity;

architecture behavior of mod_add is
constant modulo_c : std_logic_vector(bits-1 downto 0) := std_logic_vector(to_unsigned(modulo, bits));
signal q_int : std_logic_vector(bits downto 0) := (others => '0');
signal q_out : std_logic_vector(bits downto 0) := (others => '0');
begin
process(clk)
begin
if rising_edge(clk) then
if rst = '1' then
q_int <= (others => '0');
q_out <= (others => '0');
else
q_int <= std_logic_vector(unsigned("0" & a) + unsigned("0" & b));
if unsigned(q_int) >= unsigned("0" & modulo_c) then
q_out <= std_logic_vector(unsigned(q_int) - unsigned(modulo_c));
else
q_out <= q_int;
end if;
end if;
end if;
end process;

q <= q_out(bits-1 downto 0);
end architecture behavior;

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity mod_mul is
generic(
bits : positive := 16;
modulo : positive := 15
);
port(
clk : in std_logic;
rst : in std_logic;
load : in std_logic;
ready : out std_logic := '0';
a : in std_logic_vector(bits-1 downto 0);
b : in std_logic_vector(bits-1 downto 0);
q : out std_logic_vector(bits-1 downto 0) := (others => '0')
);
end entity;

architecture behavior of mod_mul is
component mod_add
generic(
bits : positive := 16;
modulo : positive := 15
);
port(
clk : in std_logic;
rst : in std_logic;
a : in std_logic_vector(bits-1 downto 0);
b : in std_logic_vector(bits-1 downto 0);
q : out std_logic_vector(bits-1 downto 0)
);
end component mod_add;

constant p_c : std_logic_vector(bits-1 downto 0) := std_logic_vector(to_unsigned(modulo, bits));
signal q_int : std_logic_vector(bits downto 0) := (others => '0');
signal q_out : std_logic_vector(bits downto 0) := (others => '0');

constant b_zero : std_logic_vector(bits-1 downto 0) := (others => '0');
signal b_shift : std_logic_vector(bits-1 downto 0) := (others => '0');
signal culm : std_logic_vector(bits-1 downto 0) := (others => '0');
signal val : std_logic_vector(bits-1 downto 0) := (others => '0');
signal culm_add_val : std_logic_vector(bits-1 downto 0) := (others => '0');
signal val_double : std_logic_vector(bits-1 downto 0) := (others => '0');
signal counter : std_logic_vector(1 downto 0) := "00";
begin
culm_add_val_proc: mod_add generic map(
bits => bits,
modulo => modulo
) port map(
clk => clk,
rst => rst,
a => culm,
b => val,
q => culm_add_val
);

val_double_proc: mod_add generic map(
bits => bits,
modulo => modulo
) port map(
clk => clk,
rst => rst,
a => val,
b => val,
q => val_double
);

process(clk)
begin
if rising_edge(clk) then
if rst = '1' then
counter <= (others => '0');
elsif load = '1' then
counter <= (others => '0');
else
counter <= std_logic_vector(unsigned(counter) + 1);
end if;
end if;
end process;

process(clk)
begin
if rising_edge(clk) then
if rst = '1' then
culm <= (others => '0');
val <= (others => '0');
elsif load = '1' then
culm <= (others => '0');
val <= a;
b_shift <= b;
elsif counter = "10" then
if b_shift(0) = '1' then
culm <= culm_add_val;
end if;
val <= val_double;
b_shift <= "0" & b_shift(bits-1 downto 1);
end if;
end if;
end process;

q <= culm;
ready <= '1' when b_shift = b_zero else '0';
end architecture behavior;


And the test bench for mod_mul:



library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity test_mod_mul is
end entity test_mod_mul;

architecture behavioral of test_mod_mul is
component mod_mul
generic(
bits : positive := 16;
modulo : positive := 15
);
port(
clk : in std_logic;
rst : in std_logic;
load : in std_logic;
ready : out std_logic;
a : in std_logic_vector(bits-1 downto 0);
b : in std_logic_vector(bits-1 downto 0);
q : out std_logic_vector(bits-1 downto 0)
);
end component mod_mul;

constant clk_period : time := 20 ns;
signal halt : boolean := false;

signal clk : std_logic := '0';
signal rst : std_logic := '0';
signal load : std_logic := '0';
signal a, b : std_logic_vector(15 downto 0);
signal a_in, b_in : integer := 0;

signal ready : std_logic;
signal q : std_logic_vector(15 downto 0);
signal q_out : integer;
begin
uut: mod_mul port map(
clk => clk,
rst => rst,
load => load,
ready => ready,
a => a,
b => b,
q => q
);

a <= std_logic_vector(to_unsigned(a_in, a'length));
b <= std_logic_vector(to_unsigned(b_in, b'length));
q_out <= to_integer(unsigned(q));

process
begin
clk <= '1';
wait for clk_period/2;
clk <= '0';
wait for clk_period/2;
if halt then
wait;
end if;
end process;

process
procedure check_multiply(
constant a, b : in integer;
constant q : in integer) is
begin
wait until falling_edge(clk);
a_in <= a;
b_in <= b;
load <= '1';
wait for clk_period;
load <= '0';
wait until rising_edge(clk) and ready = '1';
assert q_out = q report "Failed mod multiplication" severity error;
end procedure check_multiply;
begin
rst <= '1';
wait for 10*clk_period;
rst <= '0';
wait for clk_period;
assert ready = '1' report "Not ready" severity error;
assert q_out = 0 report "Failed mod multiplication" severity failure;

check_multiply(2, 2, 4);
check_multiply(2, 3, 6);
check_multiply(3, 3, 9);
check_multiply(4, 4, 1);
check_multiply(6, 5, 0);
check_multiply(6, 7, 12);

wait for 1000 ns;
halt <= true;
wait;
end process;
end architecture behavioral;






share|improve this question



















  • Can I ask what you are designing? ASIC? FPGA? What synthesis tools are you using? What arithmetic functions do you want to realize (in equations)?
    – JHBonarius
    Jun 26 at 19:46













up vote
1
down vote

favorite









up vote
1
down vote

favorite











I'm building some modules in VHDL for handling modular arithmetic and want to make sure it's well-designed for timing and somewhat efficient when scaling up. This will need to work with 128-bit or 256-bit arithmetic when complete, but I'm testing it currently with small 16-bit numbers currently. There are two modules, mod_add for the basic modular arithmetic, and mod_mul for the multiplication built on top of modular addition.



library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity mod_add is
generic(
bits : positive := 16;
modulo : positive := 15
);
port(
clk : in std_logic;
rst : in std_logic;
a : in std_logic_vector(bits-1 downto 0);
b : in std_logic_vector(bits-1 downto 0);
q : out std_logic_vector(bits-1 downto 0) := (others => '0')
);
end entity;

architecture behavior of mod_add is
constant modulo_c : std_logic_vector(bits-1 downto 0) := std_logic_vector(to_unsigned(modulo, bits));
signal q_int : std_logic_vector(bits downto 0) := (others => '0');
signal q_out : std_logic_vector(bits downto 0) := (others => '0');
begin
process(clk)
begin
if rising_edge(clk) then
if rst = '1' then
q_int <= (others => '0');
q_out <= (others => '0');
else
q_int <= std_logic_vector(unsigned("0" & a) + unsigned("0" & b));
if unsigned(q_int) >= unsigned("0" & modulo_c) then
q_out <= std_logic_vector(unsigned(q_int) - unsigned(modulo_c));
else
q_out <= q_int;
end if;
end if;
end if;
end process;

q <= q_out(bits-1 downto 0);
end architecture behavior;

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity mod_mul is
generic(
bits : positive := 16;
modulo : positive := 15
);
port(
clk : in std_logic;
rst : in std_logic;
load : in std_logic;
ready : out std_logic := '0';
a : in std_logic_vector(bits-1 downto 0);
b : in std_logic_vector(bits-1 downto 0);
q : out std_logic_vector(bits-1 downto 0) := (others => '0')
);
end entity;

architecture behavior of mod_mul is
component mod_add
generic(
bits : positive := 16;
modulo : positive := 15
);
port(
clk : in std_logic;
rst : in std_logic;
a : in std_logic_vector(bits-1 downto 0);
b : in std_logic_vector(bits-1 downto 0);
q : out std_logic_vector(bits-1 downto 0)
);
end component mod_add;

constant p_c : std_logic_vector(bits-1 downto 0) := std_logic_vector(to_unsigned(modulo, bits));
signal q_int : std_logic_vector(bits downto 0) := (others => '0');
signal q_out : std_logic_vector(bits downto 0) := (others => '0');

constant b_zero : std_logic_vector(bits-1 downto 0) := (others => '0');
signal b_shift : std_logic_vector(bits-1 downto 0) := (others => '0');
signal culm : std_logic_vector(bits-1 downto 0) := (others => '0');
signal val : std_logic_vector(bits-1 downto 0) := (others => '0');
signal culm_add_val : std_logic_vector(bits-1 downto 0) := (others => '0');
signal val_double : std_logic_vector(bits-1 downto 0) := (others => '0');
signal counter : std_logic_vector(1 downto 0) := "00";
begin
culm_add_val_proc: mod_add generic map(
bits => bits,
modulo => modulo
) port map(
clk => clk,
rst => rst,
a => culm,
b => val,
q => culm_add_val
);

val_double_proc: mod_add generic map(
bits => bits,
modulo => modulo
) port map(
clk => clk,
rst => rst,
a => val,
b => val,
q => val_double
);

process(clk)
begin
if rising_edge(clk) then
if rst = '1' then
counter <= (others => '0');
elsif load = '1' then
counter <= (others => '0');
else
counter <= std_logic_vector(unsigned(counter) + 1);
end if;
end if;
end process;

process(clk)
begin
if rising_edge(clk) then
if rst = '1' then
culm <= (others => '0');
val <= (others => '0');
elsif load = '1' then
culm <= (others => '0');
val <= a;
b_shift <= b;
elsif counter = "10" then
if b_shift(0) = '1' then
culm <= culm_add_val;
end if;
val <= val_double;
b_shift <= "0" & b_shift(bits-1 downto 1);
end if;
end if;
end process;

q <= culm;
ready <= '1' when b_shift = b_zero else '0';
end architecture behavior;


And the test bench for mod_mul:



library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity test_mod_mul is
end entity test_mod_mul;

architecture behavioral of test_mod_mul is
component mod_mul
generic(
bits : positive := 16;
modulo : positive := 15
);
port(
clk : in std_logic;
rst : in std_logic;
load : in std_logic;
ready : out std_logic;
a : in std_logic_vector(bits-1 downto 0);
b : in std_logic_vector(bits-1 downto 0);
q : out std_logic_vector(bits-1 downto 0)
);
end component mod_mul;

constant clk_period : time := 20 ns;
signal halt : boolean := false;

signal clk : std_logic := '0';
signal rst : std_logic := '0';
signal load : std_logic := '0';
signal a, b : std_logic_vector(15 downto 0);
signal a_in, b_in : integer := 0;

signal ready : std_logic;
signal q : std_logic_vector(15 downto 0);
signal q_out : integer;
begin
uut: mod_mul port map(
clk => clk,
rst => rst,
load => load,
ready => ready,
a => a,
b => b,
q => q
);

a <= std_logic_vector(to_unsigned(a_in, a'length));
b <= std_logic_vector(to_unsigned(b_in, b'length));
q_out <= to_integer(unsigned(q));

process
begin
clk <= '1';
wait for clk_period/2;
clk <= '0';
wait for clk_period/2;
if halt then
wait;
end if;
end process;

process
procedure check_multiply(
constant a, b : in integer;
constant q : in integer) is
begin
wait until falling_edge(clk);
a_in <= a;
b_in <= b;
load <= '1';
wait for clk_period;
load <= '0';
wait until rising_edge(clk) and ready = '1';
assert q_out = q report "Failed mod multiplication" severity error;
end procedure check_multiply;
begin
rst <= '1';
wait for 10*clk_period;
rst <= '0';
wait for clk_period;
assert ready = '1' report "Not ready" severity error;
assert q_out = 0 report "Failed mod multiplication" severity failure;

check_multiply(2, 2, 4);
check_multiply(2, 3, 6);
check_multiply(3, 3, 9);
check_multiply(4, 4, 1);
check_multiply(6, 5, 0);
check_multiply(6, 7, 12);

wait for 1000 ns;
halt <= true;
wait;
end process;
end architecture behavioral;






share|improve this question











I'm building some modules in VHDL for handling modular arithmetic and want to make sure it's well-designed for timing and somewhat efficient when scaling up. This will need to work with 128-bit or 256-bit arithmetic when complete, but I'm testing it currently with small 16-bit numbers currently. There are two modules, mod_add for the basic modular arithmetic, and mod_mul for the multiplication built on top of modular addition.



library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity mod_add is
generic(
bits : positive := 16;
modulo : positive := 15
);
port(
clk : in std_logic;
rst : in std_logic;
a : in std_logic_vector(bits-1 downto 0);
b : in std_logic_vector(bits-1 downto 0);
q : out std_logic_vector(bits-1 downto 0) := (others => '0')
);
end entity;

architecture behavior of mod_add is
constant modulo_c : std_logic_vector(bits-1 downto 0) := std_logic_vector(to_unsigned(modulo, bits));
signal q_int : std_logic_vector(bits downto 0) := (others => '0');
signal q_out : std_logic_vector(bits downto 0) := (others => '0');
begin
process(clk)
begin
if rising_edge(clk) then
if rst = '1' then
q_int <= (others => '0');
q_out <= (others => '0');
else
q_int <= std_logic_vector(unsigned("0" & a) + unsigned("0" & b));
if unsigned(q_int) >= unsigned("0" & modulo_c) then
q_out <= std_logic_vector(unsigned(q_int) - unsigned(modulo_c));
else
q_out <= q_int;
end if;
end if;
end if;
end process;

q <= q_out(bits-1 downto 0);
end architecture behavior;

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity mod_mul is
generic(
bits : positive := 16;
modulo : positive := 15
);
port(
clk : in std_logic;
rst : in std_logic;
load : in std_logic;
ready : out std_logic := '0';
a : in std_logic_vector(bits-1 downto 0);
b : in std_logic_vector(bits-1 downto 0);
q : out std_logic_vector(bits-1 downto 0) := (others => '0')
);
end entity;

architecture behavior of mod_mul is
component mod_add
generic(
bits : positive := 16;
modulo : positive := 15
);
port(
clk : in std_logic;
rst : in std_logic;
a : in std_logic_vector(bits-1 downto 0);
b : in std_logic_vector(bits-1 downto 0);
q : out std_logic_vector(bits-1 downto 0)
);
end component mod_add;

constant p_c : std_logic_vector(bits-1 downto 0) := std_logic_vector(to_unsigned(modulo, bits));
signal q_int : std_logic_vector(bits downto 0) := (others => '0');
signal q_out : std_logic_vector(bits downto 0) := (others => '0');

constant b_zero : std_logic_vector(bits-1 downto 0) := (others => '0');
signal b_shift : std_logic_vector(bits-1 downto 0) := (others => '0');
signal culm : std_logic_vector(bits-1 downto 0) := (others => '0');
signal val : std_logic_vector(bits-1 downto 0) := (others => '0');
signal culm_add_val : std_logic_vector(bits-1 downto 0) := (others => '0');
signal val_double : std_logic_vector(bits-1 downto 0) := (others => '0');
signal counter : std_logic_vector(1 downto 0) := "00";
begin
culm_add_val_proc: mod_add generic map(
bits => bits,
modulo => modulo
) port map(
clk => clk,
rst => rst,
a => culm,
b => val,
q => culm_add_val
);

val_double_proc: mod_add generic map(
bits => bits,
modulo => modulo
) port map(
clk => clk,
rst => rst,
a => val,
b => val,
q => val_double
);

process(clk)
begin
if rising_edge(clk) then
if rst = '1' then
counter <= (others => '0');
elsif load = '1' then
counter <= (others => '0');
else
counter <= std_logic_vector(unsigned(counter) + 1);
end if;
end if;
end process;

process(clk)
begin
if rising_edge(clk) then
if rst = '1' then
culm <= (others => '0');
val <= (others => '0');
elsif load = '1' then
culm <= (others => '0');
val <= a;
b_shift <= b;
elsif counter = "10" then
if b_shift(0) = '1' then
culm <= culm_add_val;
end if;
val <= val_double;
b_shift <= "0" & b_shift(bits-1 downto 1);
end if;
end if;
end process;

q <= culm;
ready <= '1' when b_shift = b_zero else '0';
end architecture behavior;


And the test bench for mod_mul:



library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity test_mod_mul is
end entity test_mod_mul;

architecture behavioral of test_mod_mul is
component mod_mul
generic(
bits : positive := 16;
modulo : positive := 15
);
port(
clk : in std_logic;
rst : in std_logic;
load : in std_logic;
ready : out std_logic;
a : in std_logic_vector(bits-1 downto 0);
b : in std_logic_vector(bits-1 downto 0);
q : out std_logic_vector(bits-1 downto 0)
);
end component mod_mul;

constant clk_period : time := 20 ns;
signal halt : boolean := false;

signal clk : std_logic := '0';
signal rst : std_logic := '0';
signal load : std_logic := '0';
signal a, b : std_logic_vector(15 downto 0);
signal a_in, b_in : integer := 0;

signal ready : std_logic;
signal q : std_logic_vector(15 downto 0);
signal q_out : integer;
begin
uut: mod_mul port map(
clk => clk,
rst => rst,
load => load,
ready => ready,
a => a,
b => b,
q => q
);

a <= std_logic_vector(to_unsigned(a_in, a'length));
b <= std_logic_vector(to_unsigned(b_in, b'length));
q_out <= to_integer(unsigned(q));

process
begin
clk <= '1';
wait for clk_period/2;
clk <= '0';
wait for clk_period/2;
if halt then
wait;
end if;
end process;

process
procedure check_multiply(
constant a, b : in integer;
constant q : in integer) is
begin
wait until falling_edge(clk);
a_in <= a;
b_in <= b;
load <= '1';
wait for clk_period;
load <= '0';
wait until rising_edge(clk) and ready = '1';
assert q_out = q report "Failed mod multiplication" severity error;
end procedure check_multiply;
begin
rst <= '1';
wait for 10*clk_period;
rst <= '0';
wait for clk_period;
assert ready = '1' report "Not ready" severity error;
assert q_out = 0 report "Failed mod multiplication" severity failure;

check_multiply(2, 2, 4);
check_multiply(2, 3, 6);
check_multiply(3, 3, 9);
check_multiply(4, 4, 1);
check_multiply(6, 5, 0);
check_multiply(6, 7, 12);

wait for 1000 ns;
halt <= true;
wait;
end process;
end architecture behavioral;








share|improve this question










share|improve this question




share|improve this question









asked Jun 8 at 8:52









penguin359

1111




1111











  • Can I ask what you are designing? ASIC? FPGA? What synthesis tools are you using? What arithmetic functions do you want to realize (in equations)?
    – JHBonarius
    Jun 26 at 19:46

















  • Can I ask what you are designing? ASIC? FPGA? What synthesis tools are you using? What arithmetic functions do you want to realize (in equations)?
    – JHBonarius
    Jun 26 at 19:46
















Can I ask what you are designing? ASIC? FPGA? What synthesis tools are you using? What arithmetic functions do you want to realize (in equations)?
– JHBonarius
Jun 26 at 19:46





Can I ask what you are designing? ASIC? FPGA? What synthesis tools are you using? What arithmetic functions do you want to realize (in equations)?
– JHBonarius
Jun 26 at 19:46
















active

oldest

votes











Your Answer




StackExchange.ifUsing("editor", function ()
return StackExchange.using("mathjaxEditing", function ()
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
);
);
, "mathjax-editing");

StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");

StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "196"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
convertImagesToLinks: false,
noModals: false,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);








 

draft saved


draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f196101%2fq-efficient-modular-arithmetic-in-vhdl%23new-answer', 'question_page');

);

Post as a guest



































active

oldest

votes













active

oldest

votes









active

oldest

votes






active

oldest

votes










 

draft saved


draft discarded


























 


draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f196101%2fq-efficient-modular-arithmetic-in-vhdl%23new-answer', 'question_page');

);

Post as a guest













































































Popular posts from this blog

Greedy Best First Search implementation in Rust

Function to Return a JSON Like Objects Using VBA Collections and Arrays

C++11 CLH Lock Implementation