Skip to content
Snippets Groups Projects
Commit 40afe21c authored by Daniel van der Schuur's avatar Daniel van der Schuur
Browse files

-Added canonical version of complex multiplier (uses 3 mults and 5 adds).

parent 503f3654
No related branches found
No related tags found
No related merge requests found
hdl_lib_name = ip_arria10_complex_mult_rtl_canonical
hdl_library_clause_name = ip_arria10_complex_mult_rtl_lib_canonical
hdl_lib_uses_synth =
hdl_lib_uses_sim =
hdl_lib_technology = #ip_arria10 This file is also used for arria10_e3sge3 and arria10_e1sg
synth_files =
ip_arria10_complex_mult_rtl_canonical.vhd
test_bench_files =
[modelsim_project_file]
[quartus_project_file]
-------------------------------------------------------------------------------
--
-- Copyright (C) 2018
-- 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/>.
--
-------------------------------------------------------------------------------
-- Authors:
-- . Daniel van der Schuur
-- Purpose:
-- . RTL complex multiplier, canonical version (3 simple multipliers).
-- Description:
-- . re = ((ar+ai)*(br-bi))+(ar*bi-ai*br)
-- im = ar*bi+ai*br
-- Remark:
-- . g_conjugate_b is not supported!
LIBRARY IEEE;
USE IEEE.std_logic_1164.ALL;
USE IEEE.numeric_std.ALL;
ENTITY ip_arria10_complex_mult_rtl_canonical IS
GENERIC (
g_in_a_w : POSITIVE;
g_in_b_w : POSITIVE;
g_out_p_w : POSITIVE; -- default use g_out_p_w = g_in_a_w+g_in_b_w = c_prod_w
-- g_conjugate_b : BOOLEAN := FALSE;
g_pipeline_input : NATURAL := 1; -- 0 or 1
g_pipeline_product : NATURAL := 0; -- 0 or 1
g_pipeline_adder : NATURAL := 1; -- 0 or 1
g_pipeline_output : NATURAL := 1 -- >= 0
);
PORT (
rst : IN STD_LOGIC := '0';
clk : IN STD_LOGIC;
clken : IN STD_LOGIC := '1';
in_ar : IN STD_LOGIC_VECTOR(g_in_a_w-1 DOWNTO 0);
in_ai : IN STD_LOGIC_VECTOR(g_in_a_w-1 DOWNTO 0);
in_br : IN STD_LOGIC_VECTOR(g_in_b_w-1 DOWNTO 0);
in_bi : IN STD_LOGIC_VECTOR(g_in_b_w-1 DOWNTO 0);
result_re : OUT STD_LOGIC_VECTOR(g_out_p_w-1 DOWNTO 0);
result_im : OUT STD_LOGIC_VECTOR(g_out_p_w-1 DOWNTO 0)
);
END ip_arria10_complex_mult_rtl_canonical;
ARCHITECTURE str OF ip_arria10_complex_mult_rtl_canonical IS
FUNCTION RESIZE_NUM(s : SIGNED; w : NATURAL) RETURN SIGNED IS
BEGIN
-- extend sign bit or keep LS part
IF w>s'LENGTH THEN
RETURN RESIZE(s, w); -- extend sign bit
ELSE
RETURN SIGNED(RESIZE(UNSIGNED(s), w)); -- keep LSbits (= vec[w-1:0])
END IF;
END;
FUNCTION largest(n, m : INTEGER) RETURN INTEGER IS
BEGIN
IF n > m THEN
RETURN n;
ELSE
RETURN m;
END IF;
END;
-----------------------------------------------------------------------------
-- Multiply / add output signals
-- . re = ((ar+ai)*(br-bi))+(ar*bi-ai*br)
-- im = ar*bi+ai*br
-----------------------------------------------------------------------------
CONSTANT c_sum_ar_ai_w : NATURAL := g_in_a_w+1; -- sum_ar_ai
CONSTANT c_sum_br_bi_w : NATURAL := g_in_b_w+1; -- sum_br_bi
CONSTANT c_prod_w : NATURAL := g_in_a_w+g_in_b_w; -- prod_ar_bi, prod_ai_br
CONSTANT c_sum_prod_w : NATURAL := c_prod_w+1; -- sum_prod_ar_bi_prod_ai_br
CONSTANT c_prod_sum_w : NATURAL := c_sum_ar_ai_w+c_sum_br_bi_w; -- prod_sum_ar_ai_sum_br_bi
CONSTANT c_sum_im_w : NATURAL := c_prod_w+1; -- sum_im
CONSTANT c_sum_re_w : NATURAL := largest(c_sum_prod_w, c_prod_sum_w)+1; -- sum_re
SIGNAL sum_ar_ai : SIGNED(c_sum_ar_ai_w-1 DOWNTO 0); -- ar+ai : used in re
SIGNAL sum_br_bi : SIGNED(c_sum_br_bi_w-1 DOWNTO 0); -- br-bi : used in re
SIGNAL sum_prod_ar_bi_prod_ai_br : SIGNED(c_sum_prod_w-1 DOWNTO 0); -- ar*bi-ai*br : used in re
SIGNAL sum_im : SIGNED(c_sum_im_w-1 DOWNTO 0); -- ar*bi+ai*br : im
SIGNAL sum_re : SIGNED(c_sum_re_w-1 DOWNTO 0); -- ((ar+ai)*(br-bi))+(ar*bi-ai*br) : re
SIGNAL prod_ar_bi : SIGNED(c_prod_w-1 DOWNTO 0); -- ar*bi : used in re and im
SIGNAL prod_ai_br : SIGNED(c_prod_w-1 DOWNTO 0); -- ai*br : used in re and im
SIGNAL prod_sum_ar_ai_sum_br_bi : SIGNED(c_prod_sum_w-1 DOWNTO 0); -- (ar+ai)*(br-bi) : used in re
-----------------------------------------------------------------------------
-- register signals
-----------------------------------------------------------------------------
SIGNAL ar : SIGNED(g_in_a_w-1 DOWNTO 0);
SIGNAL ai : SIGNED(g_in_a_w-1 DOWNTO 0);
SIGNAL br : SIGNED(g_in_b_w-1 DOWNTO 0);
SIGNAL bi : SIGNED(g_in_b_w-1 DOWNTO 0);
SIGNAL nxt_ar : SIGNED(g_in_a_w-1 DOWNTO 0);
SIGNAL nxt_ai : SIGNED(g_in_a_w-1 DOWNTO 0);
SIGNAL nxt_br : SIGNED(g_in_b_w-1 DOWNTO 0);
SIGNAL nxt_bi : SIGNED(g_in_b_w-1 DOWNTO 0);
SIGNAL reg_ar : SIGNED(g_in_a_w-1 DOWNTO 0);
SIGNAL reg_ai : SIGNED(g_in_a_w-1 DOWNTO 0);
SIGNAL reg_br : SIGNED(g_in_b_w-1 DOWNTO 0);
SIGNAL reg_bi : SIGNED(g_in_b_w-1 DOWNTO 0);
SIGNAL nxt_sum_ar_ai : SIGNED(c_sum_ar_ai_w-1 DOWNTO 0);
SIGNAL nxt_sum_br_bi : SIGNED(c_sum_br_bi_w-1 DOWNTO 0);
SIGNAL nxt_sum_prod_ar_bi_prod_ai_br : SIGNED(c_sum_prod_w-1 DOWNTO 0);
SIGNAL nxt_sum_im : SIGNED(c_sum_im_w-1 DOWNTO 0);
SIGNAL nxt_sum_re : SIGNED(c_sum_re_w-1 DOWNTO 0);
SIGNAL nxt_prod_ar_bi : SIGNED(c_prod_w-1 DOWNTO 0);
SIGNAL nxt_prod_ai_br : SIGNED(c_prod_w-1 DOWNTO 0);
SIGNAL nxt_prod_sum_ar_ai_sum_br_bi : SIGNED(c_prod_sum_w-1 DOWNTO 0);
SIGNAL reg_sum_ar_ai : SIGNED(c_sum_ar_ai_w-1 DOWNTO 0);
SIGNAL reg_sum_br_bi : SIGNED(c_sum_br_bi_w-1 DOWNTO 0);
SIGNAL reg_sum_prod_ar_bi_prod_ai_br : SIGNED(c_sum_prod_w-1 DOWNTO 0);
SIGNAL reg_sum_im : SIGNED(c_sum_im_w-1 DOWNTO 0);
SIGNAL reg_sum_re : SIGNED(c_sum_re_w-1 DOWNTO 0);
SIGNAL reg_prod_ar_bi : SIGNED(c_prod_w-1 DOWNTO 0);
SIGNAL reg_prod_ai_br : SIGNED(c_prod_w-1 DOWNTO 0);
SIGNAL reg_prod_sum_ar_ai_sum_br_bi : SIGNED(c_prod_sum_w-1 DOWNTO 0);
SIGNAL nxt_result_re : SIGNED(g_out_p_w-1 DOWNTO 0);
SIGNAL nxt_result_im : SIGNED(g_out_p_w-1 DOWNTO 0);
SIGNAL reg_result_re : SIGNED(g_out_p_w-1 DOWNTO 0);
SIGNAL reg_result_im : SIGNED(g_out_p_w-1 DOWNTO 0);
BEGIN
------------------------------------------------------------------------------
-- Registers
------------------------------------------------------------------------------
-- Put all potential registers in a single process for optimal DSP inferrence
-- Use rst only if it is supported by the DSP primitive, else leave it at '0'
p_reg : PROCESS (rst, clk)
BEGIN
IF rising_edge(clk) THEN
IF rst='1' THEN
reg_ar <= (OTHERS=>'0');
reg_ai <= (OTHERS=>'0');
reg_br <= (OTHERS=>'0');
reg_bi <= (OTHERS=>'0');
reg_sum_ar_ai <= (OTHERS=>'0');
reg_sum_br_bi <= (OTHERS=>'0');
reg_sum_prod_ar_bi_prod_ai_br <= (OTHERS=>'0');
reg_sum_im <= (OTHERS=>'0');
reg_sum_re <= (OTHERS=>'0');
reg_prod_ar_bi <= (OTHERS=>'0');
reg_prod_ai_br <= (OTHERS=>'0');
reg_prod_sum_ar_ai_sum_br_bi <= (OTHERS=>'0');
ELSIF clken='1' THEN
reg_ar <= nxt_ar;
reg_ai <= nxt_ai;
reg_br <= nxt_br;
reg_bi <= nxt_bi;
reg_sum_ar_ai <= nxt_sum_ar_ai;
reg_sum_br_bi <= nxt_sum_br_bi;
reg_sum_prod_ar_bi_prod_ai_br <= nxt_sum_prod_ar_bi_prod_ai_br;
reg_sum_im <= nxt_sum_im;
reg_sum_re <= nxt_sum_re;
reg_prod_ar_bi <= nxt_prod_ar_bi;
reg_prod_ai_br <= nxt_prod_ai_br;
reg_prod_sum_ar_ai_sum_br_bi <= nxt_prod_sum_ar_ai_sum_br_bi;
END IF;
END IF;
END PROCESS;
------------------------------------------------------------------------------
-- Inputs
------------------------------------------------------------------------------
nxt_ar <= SIGNED(in_ar);
nxt_ai <= SIGNED(in_ai);
nxt_br <= SIGNED(in_br);
nxt_bi <= SIGNED(in_bi);
no_input_reg : IF g_pipeline_input=0 GENERATE -- wired
ar <= nxt_ar;
ai <= nxt_ai;
br <= nxt_br;
bi <= nxt_bi;
END GENERATE;
gen_input_reg : IF g_pipeline_input>0 GENERATE -- register input
ar <= reg_ar;
ai <= reg_ai;
br <= reg_br;
bi <= reg_bi;
END GENERATE;
------------------------------------------------------------------------------
-- Sums
------------------------------------------------------------------------------
nxt_sum_ar_ai <= RESIZE_NUM(ar, c_sum_ar_ai_w) + ai;
nxt_sum_br_bi <= RESIZE_NUM(br, c_sum_br_bi_w) + bi;
nxt_sum_prod_ar_bi_prod_ai_br <= RESIZE_NUM(prod_ar_bi, c_prod_sum_w) + prod_ai_br;
nxt_sum_re <= RESIZE_NUM(prod_sum_ar_ai_sum_br_bi, c_prod_sum_w), sum_prod_ar_bi_prod_ai_br;
nxt_sum_im <= RESIZE_NUM(prod_ai_br, c_sum_im_w) + prod_ar_bi;
no_adder_reg : IF g_pipeline_adder=0 GENERATE -- wired
sum_ar_ai <= nxt_sum_ar_ai;
sum_br_bi <= nxt_sum_br_bi;
sum_prod_ar_bi_prod_ai_br <= nxt_sum_prod_ar_bi_prod_ai_br;
sum_re <= nxt_sum_re;
sum_im <= nxt_sum_im;
END GENERATE;
gen_adder_reg : IF g_pipeline_adder>0 GENERATE -- register
sum_ar_ai <= reg_sum_ar_ai;
sum_br_bi <= reg_sum_br_bi;
sum_prod_ar_bi_prod_ai_br <= reg_sum_prod_ar_bi_prod_ai_br;
sum_re <= reg_sum_re;
sum_im <= reg_sum_im;
END GENERATE;
------------------------------------------------------------------------------
-- Products
------------------------------------------------------------------------------
nxt_prod_ar_bi <= ar * bi;
nxt_prod_ai_br <= ai * br;
nxt_prod_sum_ar_ai_sum_br_bi <= sum_ar_ai * sum_br_bi;
no_product_reg : IF g_pipeline_product=0 GENERATE -- wired
prod_ar_bi <= nxt_prod_ar_bi;
prod_ai_br <= nxt_prod_ai_br;
prod_sum_ar_ai_sum_br_bi <= nxt_prod_sum_ar_ai_sum_br_bi;
END GENERATE;
gen_product_reg : IF g_pipeline_product>0 GENERATE -- register
prod_ar_bi <= reg_prod_ar_bi;
prod_ai_br <= reg_prod_ai_br;
prod_sum_ar_ai_sum_br_bi <= reg_prod_sum_ar_ai_sum_br_bi;
END GENERATE;
------------------------------------------------------------------------------
-- Result sum after optional rounding
------------------------------------------------------------------------------
nxt_result_re <= RESIZE_NUM(sum_re, g_out_p_w);
nxt_result_im <= RESIZE_NUM(sum_im, g_out_p_w);
no_result_reg : IF g_pipeline_output=0 GENERATE -- wired
result_re <= STD_LOGIC_VECTOR(nxt_result_re);
result_im <= STD_LOGIC_VECTOR(nxt_result_im);
END GENERATE;
gen_result_reg : IF g_pipeline_output>0 GENERATE -- register
result_re <= STD_LOGIC_VECTOR(reg_result_re);
result_im <= STD_LOGIC_VECTOR(reg_result_im);
END GENERATE;
END ARCHITECTURE;
...@@ -33,7 +33,7 @@ LIBRARY ip_stratixiv_mult_lib; ...@@ -33,7 +33,7 @@ LIBRARY ip_stratixiv_mult_lib;
LIBRARY ip_arria10_complex_mult_altmult_complex_150; LIBRARY ip_arria10_complex_mult_altmult_complex_150;
LIBRARY ip_arria10_e1sg_complex_mult_altmult_complex_170; LIBRARY ip_arria10_e1sg_complex_mult_altmult_complex_170;
LIBRARY ip_arria10_complex_mult_rtl_lib; LIBRARY ip_arria10_complex_mult_rtl_lib;
LIBRARY ip_arria10_complex_mult_rtl_canonical_lib;
ENTITY tech_complex_mult IS ENTITY tech_complex_mult IS
GENERIC ( GENERIC (
...@@ -165,6 +165,7 @@ begin ...@@ -165,6 +165,7 @@ begin
result_im <= RESIZE_SVEC(mult_im, g_out_p_w); result_im <= RESIZE_SVEC(mult_im, g_out_p_w);
END GENERATE; END GENERATE;
-- RTL variant is the same for unb2, unb2a and unb2b -- RTL variant is the same for unb2, unb2a and unb2b
gen_ip_arria10_rtl : IF (g_sim=FALSE OR (g_sim=TRUE AND g_sim_level=0)) AND gen_ip_arria10_rtl : IF (g_sim=FALSE OR (g_sim=TRUE AND g_sim_level=0)) AND
((g_technology=c_tech_arria10 OR g_technology=c_tech_arria10_e3sge3 OR g_technology=c_tech_arria10_e1sg ) AND g_variant="RTL") GENERATE ((g_technology=c_tech_arria10 OR g_technology=c_tech_arria10_e3sge3 OR g_technology=c_tech_arria10_e1sg ) AND g_variant="RTL") GENERATE
...@@ -192,6 +193,32 @@ begin ...@@ -192,6 +193,32 @@ begin
); );
END GENERATE; END GENERATE;
gen_ip_arria10_rtl_canonical : IF (g_sim=FALSE OR (g_sim=TRUE AND g_sim_level=0)) AND
((g_technology=c_tech_arria10 OR g_technology=c_tech_arria10_e3sge3 OR g_technology=c_tech_arria10_e1sg ) AND g_variant="RTL_C") GENERATE
u0 : ip_arria10_complex_mult_rtl_canonical
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_conjugate_b => g_conjugate_b, -- NOT SUPPORTED
g_pipeline_input => g_pipeline_input,
g_pipeline_product => g_pipeline_product,
g_pipeline_adder => g_pipeline_adder,
g_pipeline_output => g_pipeline_output
)
PORT MAP(
rst => rst,
clk => clk,
clken => clken,
in_ar => in_ar,
in_ai => in_ai,
in_br => in_br,
in_bi => in_bi,
result_re => result_re,
result_im => result_im
);
END GENERATE;
gen_ip_arria10_e1sg_ip : IF (g_sim=FALSE OR (g_sim=TRUE AND g_sim_level=0)) AND (g_technology=c_tech_arria10_e1sg AND g_variant="IP") GENERATE gen_ip_arria10_e1sg_ip : IF (g_sim=FALSE OR (g_sim=TRUE AND g_sim_level=0)) AND (g_technology=c_tech_arria10_e1sg AND g_variant="IP") GENERATE
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment