URL
https://opencores.org/ocsvn/astron_multiplier/astron_multiplier/trunk
Subversion Repositories astron_multiplier
Compare Revisions
- This comparison shows the changes necessary to convert path
/astron_multiplier
- from Rev 4 to Rev 5
- ↔ Reverse comparison
Rev 4 → Rev 5
/trunk/common_mult.vhd
0,0 → 1,132
------------------------------------------------------------------------------- |
-- |
-- Copyright (C) 2011 |
-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/> |
-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands |
-- |
-- This program is free software: you can redistribute it and/or modify |
-- it under the terms of the GNU General Public License as published by |
-- the Free Software Foundation, either version 3 of the License, or |
-- (at your option) any later version. |
-- |
-- This program is distributed in the hope that it will be useful, |
-- but WITHOUT ANY WARRANTY; without even the implied warranty of |
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
-- GNU General Public License for more details. |
-- |
-- You should have received a copy of the GNU General Public License |
-- along with this program. If not, see <http://www.gnu.org/licenses/>. |
-- |
------------------------------------------------------------------------------- |
|
LIBRARY ieee, common_pkg_lib, common_components_lib; |
USE ieee.std_logic_1164.ALL; |
--USE technology_lib.technology_select_pkg.ALL; |
USE common_pkg_lib.common_pkg.ALL; |
|
-- Function: Default one or more independent products dependent on g_nof_mult |
-- |
-- If g_nof_mult = 2 then the input vectors are |
-- a = a(1) & a(0) and b = b(1) & b(0) |
-- and the independent products in the product vector will be: |
-- p = a(1)*b(1) & a(0)*b(0) |
-- |
-- Remarks: |
-- . When g_out_p_w < g_in_a_w+g_in_b_w then the common_mult truncates the |
-- MSbit of the product. |
-- . For c_prod_w = g_in_a_w+g_in_b_w the full product range is preserved. Use |
-- g_out_p_w = c_prod_w-1 to skip the double sign bit that is only needed |
-- when the maximum positive product -2**(g_in_a_w-1) * -2**(g_in_b_w-1) has |
-- to be represented, which is typically not needed in DSP. |
|
ENTITY common_mult IS |
GENERIC ( |
g_technology : NATURAL := 0; |
g_variant : STRING := "IP"; |
g_in_a_w : POSITIVE := 18; |
g_in_b_w : POSITIVE := 18; |
g_out_p_w : POSITIVE := 36; -- c_prod_w = g_in_a_w+g_in_b_w, use smaller g_out_p_w to truncate MSbits, or larger g_out_p_w to extend MSbits |
g_nof_mult : POSITIVE := 1; -- using 2 for 18x18, 4 for 9x9 may yield better results when inferring * is used |
g_pipeline_input : NATURAL := 1; -- 0 or 1 |
g_pipeline_product : NATURAL := 1; -- 0 or 1 |
g_pipeline_output : NATURAL := 1; -- >= 0 |
g_representation : STRING := "SIGNED" -- or "UNSIGNED" |
); |
PORT ( |
rst : IN STD_LOGIC := '0'; |
clk : IN STD_LOGIC; |
clken : IN STD_LOGIC := '1'; |
in_a : IN STD_LOGIC_VECTOR(g_nof_mult*g_in_a_w-1 DOWNTO 0); |
in_b : IN STD_LOGIC_VECTOR(g_nof_mult*g_in_b_w-1 DOWNTO 0); |
in_val : IN STD_LOGIC := '1'; -- only propagate valid, not used internally |
out_p : OUT STD_LOGIC_VECTOR(g_nof_mult*g_out_p_w-1 DOWNTO 0); |
out_val : OUT STD_LOGIC |
); |
END common_mult; |
|
ARCHITECTURE str OF common_mult IS |
|
CONSTANT c_pipeline : NATURAL := g_pipeline_input + g_pipeline_product + g_pipeline_output; |
|
-- Extra output pipelining using common_pipeline is only needed when g_pipeline_output > 1 |
CONSTANT c_pipeline_output : NATURAL := sel_a_b(g_pipeline_output>0, g_pipeline_output-1, 0); |
|
SIGNAL result : STD_LOGIC_VECTOR(out_p'RANGE); -- stage dependent on g_pipeline_output being 0 or 1 |
|
BEGIN |
|
u_mult : ENTITY work.tech_mult |
GENERIC MAP( |
g_technology => g_technology, |
g_variant => g_variant, |
g_in_a_w => g_in_a_w, |
g_in_b_w => g_in_b_w, |
g_out_p_w => g_out_p_w, |
g_nof_mult => g_nof_mult, |
g_pipeline_input => g_pipeline_input, |
g_pipeline_product => g_pipeline_product, |
g_pipeline_output => g_pipeline_output, |
g_representation => g_representation |
) |
PORT MAP( |
rst => rst, |
clk => clk, |
clken => clken, |
in_a => in_a, |
in_b => in_b, |
out_p => result |
); |
|
-- Propagate in_val with c_pipeline latency |
u_out_val : ENTITY common_components_lib.common_pipeline_sl |
GENERIC MAP ( |
g_pipeline => c_pipeline |
) |
PORT MAP ( |
rst => rst, |
clk => clk, |
clken => clken, |
in_dat => in_val, |
out_dat => out_val |
); |
|
------------------------------------------------------------------------------ |
-- Extra output pipelining |
------------------------------------------------------------------------------ |
|
u_output_pipe : ENTITY common_components_lib.common_pipeline -- pipeline output |
GENERIC MAP ( |
g_representation => g_representation, |
g_pipeline => c_pipeline_output, |
g_in_dat_w => result'LENGTH, |
g_out_dat_w => result'LENGTH |
) |
PORT MAP ( |
rst => rst, |
clk => clk, |
clken => clken, |
in_dat => STD_LOGIC_VECTOR(result), |
out_dat => out_p |
); |
|
END str; |
/trunk/hdllib.cfg
18,13 → 18,18
|
common_complex_mult.vhd |
|
tech_mult.vhd |
common_mult.vhd |
|
test_bench_files = |
tb_common_complex_mult.vhd |
tb_common_mult.vhd |
tb_tb_common_mult.vhd |
|
regression_test_vhdl = |
tb_common_complex_mult.vhd |
tb_tb_common_mult.vhd |
|
|
[modelsim_project_file] |
|
|
/trunk/tb_common_mult.vhd
0,0 → 1,350
------------------------------------------------------------------------------- |
-- |
-- Copyright (C) 2009 |
-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/> |
-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands |
-- |
-- This program is free software: you can redistribute it and/or modify |
-- it under the terms of the GNU General Public License as published by |
-- the Free Software Foundation, either version 3 of the License, or |
-- (at your option) any later version. |
-- |
-- This program is distributed in the hope that it will be useful, |
-- but WITHOUT ANY WARRANTY; without even the implied warranty of |
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
-- GNU General Public License for more details. |
-- |
-- You should have received a copy of the GNU General Public License |
-- along with this program. If not, see <http://www.gnu.org/licenses/>. |
-- |
------------------------------------------------------------------------------- |
|
-- Purpose: Tb for common_mult architectures |
-- Description: |
-- The tb is self verifying. |
-- Usage: |
-- > as 10 |
-- > run -all |
|
LIBRARY IEEE, common_pkg_lib, common_components_lib; |
USE IEEE.std_logic_1164.ALL; |
USE IEEE.numeric_std.ALL; |
--USE technology_lib.technology_select_pkg.ALL; |
USE common_pkg_lib.common_pkg.ALL; |
USE common_pkg_lib.tb_common_pkg.ALL; |
|
|
ENTITY tb_common_mult IS |
GENERIC ( |
g_in_dat_w : NATURAL := 7; |
g_out_dat_w : NATURAL := 11; -- = 2*g_in_dat_w, or smaller to truncate MSbits, or larger to extend MSbits |
g_nof_mult : NATURAL := 2; |
g_pipeline_input : NATURAL := 1; |
g_pipeline_product : NATURAL := 1; |
g_pipeline_output : NATURAL := 1 |
); |
END tb_common_mult; |
|
ARCHITECTURE tb OF tb_common_mult IS |
|
CONSTANT clk_period : TIME := 10 ns; |
CONSTANT c_pipeline : NATURAL := g_pipeline_input + g_pipeline_product + g_pipeline_output; |
CONSTANT c_nof_mult : NATURAL := 2; -- fixed |
|
CONSTANT c_max_p : INTEGER := 2**(g_in_dat_w-1)-1; |
CONSTANT c_min : INTEGER := -c_max_p; |
CONSTANT c_max_n : INTEGER := -2**(g_in_dat_w-1); |
|
CONSTANT c_technology : NATURAL := 0; |
|
FUNCTION func_sresult(in_a, in_b : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS |
CONSTANT c_res_w : NATURAL := 2*g_in_dat_w; -- use sufficiently large result width |
VARIABLE v_a : STD_LOGIC_VECTOR(g_in_dat_w-1 DOWNTO 0); |
VARIABLE v_b : STD_LOGIC_VECTOR(g_in_dat_w-1 DOWNTO 0); |
VARIABLE v_result : SIGNED(c_res_w-1 DOWNTO 0); |
BEGIN |
-- Calculate expected result |
v_a := RESIZE_SVEC(in_a, g_in_dat_w); |
v_b := RESIZE_SVEC(in_b, g_in_dat_w); |
v_result := RESIZE_NUM(SIGNED(v_a)*SIGNED(v_b), c_res_w); |
RETURN RESIZE_SVEC(STD_LOGIC_VECTOR(v_result), g_out_dat_w); -- Truncate MSbits or sign extend MSBits |
END; |
|
FUNCTION func_uresult(in_a, in_b : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS |
CONSTANT c_res_w : NATURAL := 2*g_in_dat_w; -- use sufficiently large result width |
VARIABLE v_a : STD_LOGIC_VECTOR(g_in_dat_w-1 DOWNTO 0); |
VARIABLE v_b : STD_LOGIC_VECTOR(g_in_dat_w-1 DOWNTO 0); |
VARIABLE v_result : UNSIGNED(c_res_w-1 DOWNTO 0); |
BEGIN |
-- Calculate expected result |
v_a := RESIZE_UVEC(in_a, g_in_dat_w); |
v_b := RESIZE_UVEC(in_b, g_in_dat_w); |
v_result := RESIZE_NUM(UNSIGNED(v_a)*UNSIGNED(v_b), c_res_w); |
RETURN RESIZE_UVEC(STD_LOGIC_VECTOR(v_result), g_out_dat_w); -- Truncate MSbits or zero extend MSBits |
END; |
|
SIGNAL rst : STD_LOGIC; |
SIGNAL clk : STD_LOGIC := '0'; |
SIGNAL tb_end : STD_LOGIC := '0'; |
|
-- Input signals |
SIGNAL in_a : STD_LOGIC_VECTOR(g_in_dat_w-1 DOWNTO 0); |
SIGNAL in_b : STD_LOGIC_VECTOR(g_in_dat_w-1 DOWNTO 0); |
SIGNAL in_a_p : STD_LOGIC_VECTOR(g_in_dat_w-1 DOWNTO 0); |
SIGNAL in_b_p : STD_LOGIC_VECTOR(g_in_dat_w-1 DOWNTO 0); |
|
-- Product signals |
SIGNAL sresult_expected : STD_LOGIC_VECTOR(g_out_dat_w-1 DOWNTO 0); -- pipelined expected result |
SIGNAL sresult_rtl : STD_LOGIC_VECTOR(g_out_dat_w-1 DOWNTO 0); |
SIGNAL sresult_ip : STD_LOGIC_VECTOR(g_out_dat_w-1 DOWNTO 0); |
SIGNAL uresult_expected : STD_LOGIC_VECTOR(g_out_dat_w-1 DOWNTO 0); -- pipelined expected result |
SIGNAL uresult_rtl : STD_LOGIC_VECTOR(g_out_dat_w-1 DOWNTO 0); |
SIGNAL uresult_ip : STD_LOGIC_VECTOR(g_out_dat_w-1 DOWNTO 0); |
|
-- auxiliary signals |
SIGNAL in_a_arr : STD_LOGIC_VECTOR(g_nof_mult*g_in_dat_w-1 DOWNTO 0); |
SIGNAL in_b_arr : STD_LOGIC_VECTOR(g_nof_mult*g_in_dat_w-1 DOWNTO 0); |
SIGNAL out_sresult : STD_LOGIC_VECTOR(g_out_dat_w-1 DOWNTO 0); -- combinatorial expected result |
SIGNAL out_uresult : STD_LOGIC_VECTOR(g_out_dat_w-1 DOWNTO 0); -- combinatorial expected result |
SIGNAL sresult_arr_expected : STD_LOGIC_VECTOR(g_nof_mult*g_out_dat_w-1 DOWNTO 0); |
SIGNAL uresult_arr_expected : STD_LOGIC_VECTOR(g_nof_mult*g_out_dat_w-1 DOWNTO 0); |
SIGNAL sresult_arr_rtl : STD_LOGIC_VECTOR(g_nof_mult*g_out_dat_w-1 DOWNTO 0); |
SIGNAL uresult_arr_rtl : STD_LOGIC_VECTOR(g_nof_mult*g_out_dat_w-1 DOWNTO 0); |
SIGNAL sresult_arr_ip : STD_LOGIC_VECTOR(g_nof_mult*g_out_dat_w-1 DOWNTO 0); |
SIGNAL uresult_arr_ip : STD_LOGIC_VECTOR(g_nof_mult*g_out_dat_w-1 DOWNTO 0); |
|
BEGIN |
|
clk <= NOT clk OR tb_end AFTER clk_period/2; |
|
-- run 1 us |
p_in_stimuli : PROCESS |
BEGIN |
rst <= '1'; |
in_a <= TO_SVEC(0, g_in_dat_w); |
in_b <= TO_SVEC(0, g_in_dat_w); |
proc_common_wait_some_cycles(clk, 10); |
rst <= '0'; |
proc_common_wait_some_cycles(clk, 10); |
|
-- Some special combinations |
in_a <= TO_SVEC(2, g_in_dat_w); |
in_b <= TO_SVEC(3, g_in_dat_w); |
WAIT UNTIL rising_edge(clk); |
in_a <= TO_SVEC(c_max_p, g_in_dat_w); -- p*p = pp |
in_b <= TO_SVEC(c_max_p, g_in_dat_w); |
WAIT UNTIL rising_edge(clk); |
in_a <= TO_SVEC(c_max_n, g_in_dat_w); -- -p*-p = pp |
in_b <= TO_SVEC(c_max_n, g_in_dat_w); |
WAIT UNTIL rising_edge(clk); |
in_a <= TO_SVEC(c_max_p, g_in_dat_w); -- p*-p = = -pp |
in_b <= TO_SVEC(c_max_n, g_in_dat_w); |
WAIT UNTIL rising_edge(clk); |
in_a <= TO_SVEC(c_max_p, g_in_dat_w); -- p*(-p-1) = -pp - p |
in_b <= TO_SVEC(c_min, g_in_dat_w); |
WAIT UNTIL rising_edge(clk); |
in_a <= TO_SVEC(c_max_n, g_in_dat_w); -- -p*(-p-1) = pp + p |
in_b <= TO_SVEC(c_min, g_in_dat_w); |
WAIT UNTIL rising_edge(clk); |
|
proc_common_wait_some_cycles(clk, 50); |
|
-- All combinations |
FOR I IN -2**(g_in_dat_w-1) TO 2**(g_in_dat_w-1)-1 LOOP |
FOR J IN -2**(g_in_dat_w-1) TO 2**(g_in_dat_w-1)-1 LOOP |
in_a <= TO_SVEC(I, g_in_dat_w); |
in_b <= TO_SVEC(J, g_in_dat_w); |
WAIT UNTIL rising_edge(clk); |
END LOOP; |
END LOOP; |
|
proc_common_wait_some_cycles(clk, 50); |
tb_end <= '1'; |
WAIT; |
END PROCESS; |
|
-- pipeline inputs to ease comparison in the Wave window |
u_in_a_pipeline : ENTITY common_components_lib.common_pipeline |
GENERIC MAP ( |
g_representation => "SIGNED", |
g_pipeline => c_pipeline, |
g_reset_value => 0, |
g_in_dat_w => g_in_dat_w, |
g_out_dat_w => g_in_dat_w |
) |
PORT MAP ( |
rst => rst, |
clk => clk, |
clken => '1', |
in_dat => in_a, |
out_dat => in_a_p |
); |
|
u_in_b_pipeline : ENTITY common_components_lib.common_pipeline |
GENERIC MAP ( |
g_representation => "SIGNED", |
g_pipeline => c_pipeline, |
g_reset_value => 0, |
g_in_dat_w => g_in_dat_w, |
g_out_dat_w => g_in_dat_w |
) |
PORT MAP ( |
rst => rst, |
clk => clk, |
clken => '1', |
in_dat => in_b, |
out_dat => in_b_p |
); |
|
gen_wires : FOR I IN 0 TO g_nof_mult-1 GENERATE |
-- use same input for all multipliers |
in_a_arr((I+1)*g_in_dat_w-1 DOWNTO I*g_in_dat_w) <= in_a; |
in_b_arr((I+1)*g_in_dat_w-1 DOWNTO I*g_in_dat_w) <= in_b; |
-- calculate expected output only for one multiplier |
out_sresult <= func_sresult(in_a, in_b); |
out_uresult <= func_uresult(in_a, in_b); |
-- copy the expected result for all multipliers |
sresult_arr_expected((I+1)*g_out_dat_w-1 DOWNTO I*g_out_dat_w) <= sresult_expected; |
uresult_arr_expected((I+1)*g_out_dat_w-1 DOWNTO I*g_out_dat_w) <= uresult_expected; |
END GENERATE; |
|
-- use mult(0) to observe result in Wave window |
sresult_rtl <= sresult_arr_rtl(g_out_dat_w-1 DOWNTO 0); |
uresult_rtl <= uresult_arr_rtl(g_out_dat_w-1 DOWNTO 0); |
sresult_ip <= sresult_arr_ip(g_out_dat_w-1 DOWNTO 0); |
uresult_ip <= uresult_arr_ip(g_out_dat_w-1 DOWNTO 0); |
|
u_sresult : ENTITY common_components_lib.common_pipeline |
GENERIC MAP ( |
g_representation => "SIGNED", |
g_pipeline => c_pipeline, |
g_reset_value => 0, |
g_in_dat_w => g_out_dat_w, |
g_out_dat_w => g_out_dat_w |
) |
PORT MAP ( |
rst => rst, |
clk => clk, |
clken => '1', |
in_dat => out_sresult, |
out_dat => sresult_expected |
); |
|
u_uresult : ENTITY common_components_lib.common_pipeline |
GENERIC MAP ( |
g_representation => "UNSIGNED", |
g_pipeline => c_pipeline, |
g_reset_value => 0, |
g_in_dat_w => g_out_dat_w, |
g_out_dat_w => g_out_dat_w |
) |
PORT MAP ( |
rst => rst, |
clk => clk, |
clken => '1', |
in_dat => out_uresult, |
out_dat => uresult_expected |
); |
|
u_sdut_rtl : ENTITY work.common_mult |
GENERIC MAP ( |
g_technology => c_technology, |
g_variant => "RTL", |
g_in_a_w => g_in_dat_w, |
g_in_b_w => g_in_dat_w, |
g_out_p_w => g_out_dat_w, |
g_nof_mult => g_nof_mult, |
g_pipeline_input => g_pipeline_input, |
g_pipeline_product => g_pipeline_product, |
g_pipeline_output => g_pipeline_output, |
g_representation => "SIGNED" |
) |
PORT MAP ( |
rst => '0', |
clk => clk, |
clken => '1', |
in_a => in_a_arr, |
in_b => in_b_arr, |
out_p => sresult_arr_rtl |
); |
|
u_udut_rtl : ENTITY work.common_mult |
GENERIC MAP ( |
g_technology => c_technology, |
g_variant => "RTL", |
g_in_a_w => g_in_dat_w, |
g_in_b_w => g_in_dat_w, |
g_out_p_w => g_out_dat_w, |
g_nof_mult => g_nof_mult, |
g_pipeline_input => g_pipeline_input, |
g_pipeline_product => g_pipeline_product, |
g_pipeline_output => g_pipeline_output, |
g_representation => "UNSIGNED" |
) |
PORT MAP ( |
rst => '0', |
clk => clk, |
clken => '1', |
in_a => in_a_arr, |
in_b => in_b_arr, |
out_p => uresult_arr_rtl |
); |
|
u_sdut_ip : ENTITY work.common_mult |
GENERIC MAP ( |
g_technology => c_technology, |
g_variant => "IP", |
g_in_a_w => g_in_dat_w, |
g_in_b_w => g_in_dat_w, |
g_out_p_w => g_out_dat_w, |
g_nof_mult => g_nof_mult, |
g_pipeline_input => g_pipeline_input, |
g_pipeline_product => g_pipeline_product, |
g_pipeline_output => g_pipeline_output, |
g_representation => "SIGNED" |
) |
PORT MAP ( |
rst => '0', |
clk => clk, |
clken => '1', |
in_a => in_a_arr, |
in_b => in_b_arr, |
out_p => sresult_arr_ip |
); |
|
u_udut_ip : ENTITY work.common_mult |
GENERIC MAP ( |
g_technology => c_technology, |
g_variant => "IP", |
g_in_a_w => g_in_dat_w, |
g_in_b_w => g_in_dat_w, |
g_out_p_w => g_out_dat_w, |
g_nof_mult => g_nof_mult, |
g_pipeline_input => g_pipeline_input, |
g_pipeline_product => g_pipeline_product, |
g_pipeline_output => g_pipeline_output, |
g_representation => "UNSIGNED" |
) |
PORT MAP ( |
rst => '0', |
clk => clk, |
clken => '1', |
in_a => in_a_arr, |
in_b => in_b_arr, |
out_p => uresult_arr_ip |
); |
|
p_verify : PROCESS(rst, clk) |
BEGIN |
IF rst='0' THEN |
IF rising_edge(clk) THEN |
-- verify all multipliers in parallel |
ASSERT sresult_arr_rtl = sresult_arr_expected REPORT "Error: wrong Signed RTL result" SEVERITY ERROR; |
ASSERT uresult_arr_rtl = uresult_arr_expected REPORT "Error: wrong Unsigned RTL result" SEVERITY ERROR; |
ASSERT sresult_arr_ip = sresult_arr_expected REPORT "Error: wrong Signed IP result" SEVERITY ERROR; |
ASSERT uresult_arr_ip = uresult_arr_expected REPORT "Error: wrong Unsigned IP result" SEVERITY ERROR; |
END IF; |
END IF; |
END PROCESS; |
|
END tb; |
/trunk/tb_tb_common_mult.vhd
0,0 → 1,59
------------------------------------------------------------------------------- |
-- |
-- Copyright (C) 2009 |
-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/> |
-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands |
-- |
-- This program is free software: you can redistribute it and/or modify |
-- it under the terms of the GNU General Public License as published by |
-- the Free Software Foundation, either version 3 of the License, or |
-- (at your option) any later version. |
-- |
-- This program is distributed in the hope that it will be useful, |
-- but WITHOUT ANY WARRANTY; without even the implied warranty of |
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
-- GNU General Public License for more details. |
-- |
-- You should have received a copy of the GNU General Public License |
-- along with this program. If not, see <http://www.gnu.org/licenses/>. |
-- |
------------------------------------------------------------------------------- |
|
-- Usage: |
-- > as 3 |
-- > run -all |
|
LIBRARY IEEE; |
USE IEEE.std_logic_1164.ALL; |
|
ENTITY tb_tb_common_mult IS |
END tb_tb_common_mult; |
|
ARCHITECTURE tb OF tb_tb_common_mult IS |
SIGNAL tb_end : STD_LOGIC := '0'; -- declare tb_end to avoid 'No objects found' error on 'when -label tb_end' |
BEGIN |
-- g_in_dat_w : NATURAL := 7; |
-- g_out_dat_w : NATURAL := 11; -- = 2*g_in_dat_w, or smaller to truncate MSbits, or larger to extend MSbits |
-- g_nof_mult : NATURAL := 2; |
-- g_pipeline_input : NATURAL := 1; |
-- g_pipeline_product : NATURAL := 1; |
-- g_pipeline_output : NATURAL := 1 |
|
|
-- Vary g_out_dat_w |
u_mult_7_12_nof_2_pipe_1_1_1 : ENTITY work.tb_common_mult GENERIC MAP (7, 12, 2, 1, 1, 1); -- truncate extra bit |
u_mult_7_13_nof_2_pipe_1_1_1 : ENTITY work.tb_common_mult GENERIC MAP (7, 13, 2, 1, 1, 1); -- truncate double sign bit |
u_mult_7_14_nof_2_pipe_1_1_1 : ENTITY work.tb_common_mult GENERIC MAP (7, 14, 2, 1, 1, 1); -- preserve full product range |
u_mult_7_15_nof_2_pipe_1_1_1 : ENTITY work.tb_common_mult GENERIC MAP (7, 15, 2, 1, 1, 1); -- extend product |
|
-- Vary g_nof_mult |
u_mult_7_11_nof_1_pipe_1_1_1 : ENTITY work.tb_common_mult GENERIC MAP (7, 11, 1, 1, 1, 1); |
u_mult_7_11_nof_3_pipe_1_1_1 : ENTITY work.tb_common_mult GENERIC MAP (7, 11, 3, 1, 1, 1); |
|
-- Vary g_pipeline_* |
u_mult_7_11_nof_1_pipe_0_0_0 : ENTITY work.tb_common_mult GENERIC MAP (7, 11, 2, 0, 0, 0); |
u_mult_7_11_nof_1_pipe_1_0_0 : ENTITY work.tb_common_mult GENERIC MAP (7, 11, 2, 1, 0, 0); |
u_mult_7_11_nof_1_pipe_0_1_0 : ENTITY work.tb_common_mult GENERIC MAP (7, 11, 2, 0, 1, 0); |
u_mult_7_11_nof_1_pipe_0_0_1 : ENTITY work.tb_common_mult GENERIC MAP (7, 11, 2, 0, 0, 1); |
|
END tb; |
/trunk/tech_mult.vhd
0,0 → 1,160
------------------------------------------------------------------------------- |
-- |
-- Copyright (C) 2009 |
-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/> |
-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands |
-- |
-- This program is free software: you can redistribute it and/or modify |
-- it under the terms of the GNU General Public License as published by |
-- the Free Software Foundation, either version 3 of the License, or |
-- (at your option) any later version. |
-- |
-- This program is distributed in the hope that it will be useful, |
-- but WITHOUT ANY WARRANTY; without even the implied warranty of |
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
-- GNU General Public License for more details. |
-- |
-- You should have received a copy of the GNU General Public License |
-- along with this program. If not, see <http://www.gnu.org/licenses/>. |
-- |
------------------------------------------------------------------------------- |
|
LIBRARY IEEE, common_pkg_lib; |
USE IEEE.std_logic_1164.ALL; |
USE common_pkg_lib.common_pkg.ALL; |
--USE technology_lib.technology_pkg.ALL; |
--USE technology_lib.technology_select_pkg.ALL; |
USE work.tech_mult_component_pkg.ALL; |
|
-- Declare IP libraries to ensure default binding in simulation. The IP library clause is ignored by synthesis. |
--LIBRARY ip_stratixiv_mult_lib; |
--LIBRARY ip_arria10_mult_lib; |
|
|
ENTITY tech_mult IS |
GENERIC ( |
g_technology : NATURAL := 0; |
g_variant : STRING := "IP"; |
g_in_a_w : POSITIVE := 18; |
g_in_b_w : POSITIVE := 18; |
g_out_p_w : POSITIVE := 36; -- c_prod_w = g_in_a_w+g_in_b_w, use smaller g_out_p_w to truncate MSbits, or larger g_out_p_w to extend MSbits |
g_nof_mult : POSITIVE := 1; -- using 2 for 18x18, 4 for 9x9 may yield better results when inferring * is used |
g_pipeline_input : NATURAL := 1; -- 0 or 1 |
g_pipeline_product : NATURAL := 1; -- 0 or 1 |
g_pipeline_output : NATURAL := 1; -- >= 0 |
g_representation : STRING := "SIGNED" -- or "UNSIGNED" |
); |
PORT ( |
rst : IN STD_LOGIC; |
clk : IN STD_LOGIC; |
clken : IN STD_LOGIC := '1'; |
in_a : IN STD_LOGIC_VECTOR(g_nof_mult*g_in_a_w-1 DOWNTO 0); |
in_b : IN STD_LOGIC_VECTOR(g_nof_mult*g_in_b_w-1 DOWNTO 0); |
out_p : OUT STD_LOGIC_VECTOR(g_nof_mult*g_out_p_w-1 DOWNTO 0) |
); |
END tech_mult; |
|
ARCHITECTURE str of tech_mult is |
|
-- When g_out_p_w < g_in_a_w+g_in_b_w then the LPM_MULT truncates the LSbits of the product. Therefore |
-- define c_prod_w to be able to let common_mult truncate the LSBits of the product. |
CONSTANT c_prod_w : NATURAL := g_in_a_w + g_in_b_w; |
|
SIGNAL prod : STD_LOGIC_VECTOR(g_nof_mult*c_prod_w-1 DOWNTO 0); |
|
begin |
|
gen_ip_stratixiv_ip : IF (g_technology=0 AND g_variant="IP") GENERATE |
u0 : ip_stratixiv_mult |
GENERIC MAP( |
g_in_a_w => g_in_a_w, |
g_in_b_w => g_in_b_w, |
g_out_p_w => g_out_p_w, |
g_nof_mult => g_nof_mult, |
g_pipeline_input => g_pipeline_input, |
g_pipeline_product => g_pipeline_product, |
g_pipeline_output => g_pipeline_output, |
g_representation => g_representation |
) |
PORT MAP( |
clk => clk, |
clken => clken, |
in_a => in_a, |
in_b => in_b, |
out_p => prod |
); |
END GENERATE; |
|
gen_ip_stratixiv_rtl : IF (g_technology=0 AND g_variant="RTL") GENERATE |
u0 : ip_stratixiv_mult_rtl |
GENERIC MAP( |
g_in_a_w => g_in_a_w, |
g_in_b_w => g_in_b_w, |
g_out_p_w => g_out_p_w, |
g_nof_mult => g_nof_mult, |
g_pipeline_input => g_pipeline_input, |
g_pipeline_product => g_pipeline_product, |
g_pipeline_output => g_pipeline_output, |
g_representation => g_representation |
) |
PORT MAP( |
rst => rst, |
clk => clk, |
clken => clken, |
in_a => in_a, |
in_b => in_b, |
out_p => prod |
); |
END GENERATE; |
|
-- gen_ip_arria10_ip : IF ((g_technology=c_tech_arria10 OR g_technology=c_tech_arria10_e3sge3 OR g_technology=c_tech_arria10_e1sg ) AND g_variant="IP") GENERATE |
-- u0 : ip_arria10_mult |
-- GENERIC MAP( |
-- g_in_a_w => g_in_a_w, |
-- g_in_b_w => g_in_b_w, |
-- g_out_p_w => g_out_p_w, |
-- g_nof_mult => g_nof_mult, |
-- g_pipeline_input => g_pipeline_input, |
-- g_pipeline_product => g_pipeline_product, |
-- g_pipeline_output => g_pipeline_output, |
-- g_representation => g_representation |
-- ) |
-- PORT MAP( |
-- clk => clk, |
-- clken => clken, |
-- in_a => in_a, |
-- in_b => in_b, |
-- out_p => prod |
-- ); |
-- END GENERATE; |
-- |
-- gen_ip_arria10_rtl : IF ((g_technology=c_tech_arria10 OR g_technology=c_tech_arria10_e3sge3 OR g_technology=c_tech_arria10_e1sg ) AND g_variant="RTL") GENERATE |
-- u0 : ip_arria10_mult_rtl |
-- GENERIC MAP( |
-- g_in_a_w => g_in_a_w, |
-- g_in_b_w => g_in_b_w, |
-- g_out_p_w => g_out_p_w, |
-- g_nof_mult => g_nof_mult, |
-- g_pipeline_input => g_pipeline_input, |
-- g_pipeline_product => g_pipeline_product, |
-- g_pipeline_output => g_pipeline_output, |
-- g_representation => g_representation |
-- ) |
-- PORT MAP( |
-- rst => rst, |
-- clk => clk, |
-- clken => clken, |
-- in_a => in_a, |
-- in_b => in_b, |
-- out_p => prod |
-- ); |
-- END GENERATE; |
|
gen_trunk : FOR I IN 0 TO g_nof_mult-1 GENERATE |
-- Truncate MSbits, also for signed (common_pkg.vhd for explanation of RESIZE_SVEC) |
out_p((I+1)*g_out_p_w-1 DOWNTO I*g_out_p_w) <= RESIZE_SVEC(prod((I+1)*c_prod_w-1 DOWNTO I*c_prod_w), g_out_p_w) WHEN g_representation="SIGNED" ELSE |
RESIZE_UVEC(prod((I+1)*c_prod_w-1 DOWNTO I*c_prod_w), g_out_p_w); |
END GENERATE; |
|
end str; |
|