Q: Efficient modular arithmetic in VHDL
Clash 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;
vhdl
add a comment |Â
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;
vhdl
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
add a comment |Â
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;
vhdl
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;
vhdl
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
add a comment |Â
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
add a comment |Â
active
oldest
votes
active
oldest
votes
active
oldest
votes
active
oldest
votes
active
oldest
votes
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
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
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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