diff --git a/libraries/technology/ip_arria10/complex_mult_rtl_canonical/hdllib.cfg b/libraries/technology/ip_arria10/complex_mult_rtl_canonical/hdllib.cfg
new file mode 100644
index 0000000000000000000000000000000000000000..67ba589530d4341c0d5c4a1f612502fa4ee51d5b
--- /dev/null
+++ b/libraries/technology/ip_arria10/complex_mult_rtl_canonical/hdllib.cfg
@@ -0,0 +1,17 @@
+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]
+
diff --git a/libraries/technology/ip_arria10/complex_mult_rtl_canonical/ip_arria10_complex_mult_rtl_canonical.vhd b/libraries/technology/ip_arria10/complex_mult_rtl_canonical/ip_arria10_complex_mult_rtl_canonical.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..53510d0d42fdcdc5900b194173f1849f03b26720
--- /dev/null
+++ b/libraries/technology/ip_arria10/complex_mult_rtl_canonical/ip_arria10_complex_mult_rtl_canonical.vhd
@@ -0,0 +1,274 @@
+-------------------------------------------------------------------------------
+--
+-- 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;
diff --git a/libraries/technology/mult/tech_complex_mult.vhd b/libraries/technology/mult/tech_complex_mult.vhd
index 7b1368e19f3a4422d4777bb4f1f357ed3d3aebbf..82975e83418293f02b81b5045c8d1ccaa57fbe09 100644
--- a/libraries/technology/mult/tech_complex_mult.vhd
+++ b/libraries/technology/mult/tech_complex_mult.vhd
@@ -33,7 +33,7 @@ LIBRARY ip_stratixiv_mult_lib;
 LIBRARY ip_arria10_complex_mult_altmult_complex_150;
 LIBRARY ip_arria10_e1sg_complex_mult_altmult_complex_170;
 LIBRARY ip_arria10_complex_mult_rtl_lib;
-
+LIBRARY ip_arria10_complex_mult_rtl_canonical_lib;
 
 ENTITY tech_complex_mult IS
   GENERIC (
@@ -165,6 +165,7 @@ begin
     result_im <= RESIZE_SVEC(mult_im, g_out_p_w);
 
   END GENERATE;
+
   -- 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 
       ((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
     );
   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