From d0f2b6ad7319f2d259c93f35f3610e9071e1b3e9 Mon Sep 17 00:00:00 2001
From: David Brouwer <dbrouwer@astron.nl>
Date: Mon, 23 Oct 2023 08:50:28 +0200
Subject: [PATCH] Copied from
 ip_arria10_e2sg/mult_add2/ip_arria10_e2sg_mult_add2_rtl.vhd. Replaced
 information header. Changed the technology_name from ip_arria10_e2sg to
 ip_agi027_xxxx.

---
 .../ip_agi027_xxxx_mult_add2_rtl.vhd          | 202 ++++++++++++++++++
 1 file changed, 202 insertions(+)
 create mode 100644 libraries/technology/ip_agi027_xxxx/mult_add2/ip_agi027_xxxx_mult_add2_rtl.vhd

diff --git a/libraries/technology/ip_agi027_xxxx/mult_add2/ip_agi027_xxxx_mult_add2_rtl.vhd b/libraries/technology/ip_agi027_xxxx/mult_add2/ip_agi027_xxxx_mult_add2_rtl.vhd
new file mode 100644
index 0000000000..a79530ba35
--- /dev/null
+++ b/libraries/technology/ip_agi027_xxxx/mult_add2/ip_agi027_xxxx_mult_add2_rtl.vhd
@@ -0,0 +1,202 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright (C) 2023
+-- 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/>.
+--
+-------------------------------------------------------------------------------
+--
+-- Author : D.F. Brouwer
+-- Purpose: 
+--   RadioHDL wrapper
+-- Reference: 
+--   Copied from */technology/ip_arria10_e2sg/mult_add2/ip_arria10_e2sg_mult_add2.vhd,
+--   that is based on ip_stratixiv_mult_add2_rtl
+
+library IEEE, common_lib;
+use IEEE.std_logic_1164.all;
+use IEEE.numeric_std.all;
+use common_lib.common_pkg.all;
+
+------------------------------------------------------------------------------
+-- Function:
+-- . res = a0 * b0 + a1 * b1
+-- . res = a0 * b0 - a1 * b1
+------------------------------------------------------------------------------
+
+entity ip_agi027_xxxx_mult_add2_rtl is
+  generic (
+    g_in_a_w           : positive;
+    g_in_b_w           : positive;
+    g_res_w            : positive;  -- g_in_a_w + g_in_b_w + log2(2)
+    g_force_dsp        : boolean := true;  -- when TRUE resize input width to >= 18
+    g_add_sub          : string := "ADD";  -- or "SUB"
+    g_nof_mult         : integer := 2;  -- fixed
+    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_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);
+    res        : out std_logic_vector(g_res_w - 1 downto 0)
+  );
+end ip_agi027_xxxx_mult_add2_rtl;
+
+architecture str of ip_agi027_xxxx_mult_add2_rtl is
+  -- Extra output pipelining 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);
+
+  constant c_prod_w     : natural := g_in_a_w + g_in_b_w;
+  constant c_sum_w      : natural := c_prod_w + 1;
+
+  -- registers
+  signal reg_a0         : signed(g_in_a_w - 1 downto 0);
+  signal reg_b0         : signed(g_in_b_w - 1 downto 0);
+  signal reg_a1         : signed(g_in_a_w - 1 downto 0);
+  signal reg_b1         : signed(g_in_b_w - 1 downto 0);
+  signal reg_prod0      : signed(c_prod_w - 1 downto 0);
+  signal reg_prod1      : signed(c_prod_w - 1 downto 0);
+  signal reg_sum        : signed(c_sum_w - 1 downto 0);
+  signal reg_result     : signed(g_res_w - 1 downto 0);
+
+  -- combinatorial
+  signal nxt_a0     : signed(g_in_a_w - 1 downto 0);
+  signal nxt_b0     : signed(g_in_b_w - 1 downto 0);
+  signal nxt_a1     : signed(g_in_a_w - 1 downto 0);
+  signal nxt_b1     : signed(g_in_b_w - 1 downto 0);
+  signal nxt_prod0  : signed(c_prod_w - 1 downto 0);
+  signal nxt_prod1  : signed(c_prod_w - 1 downto 0);
+  signal nxt_sum    : signed(c_sum_w - 1 downto 0);
+  signal nxt_result : signed(g_res_w - 1 downto 0);
+
+  -- the active signals
+  signal a0         : signed(g_in_a_w - 1 downto 0);
+  signal b0         : signed(g_in_b_w - 1 downto 0);
+  signal a1         : signed(g_in_a_w - 1 downto 0);
+  signal b1         : signed(g_in_b_w - 1 downto 0);
+  signal prod0      : signed(c_prod_w - 1 downto 0);
+  signal prod1      : signed(c_prod_w - 1 downto 0);
+  signal sum        : signed(c_sum_w - 1 downto 0);
+  signal result     : signed(g_res_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_a0     <= (others => '0');
+        reg_b0     <= (others => '0');
+        reg_a1     <= (others => '0');
+        reg_b1     <= (others => '0');
+        reg_prod0  <= (others => '0');
+        reg_prod1  <= (others => '0');
+        reg_sum    <= (others => '0');
+        reg_result <= (others => '0');
+      elsif clken = '1' then
+        reg_a0     <= nxt_a0;  -- inputs
+        reg_b0     <= nxt_b0;
+        reg_a1     <= nxt_a1;
+        reg_b1     <= nxt_b1;
+        reg_prod0  <= nxt_prod0;  -- products
+        reg_prod1  <= nxt_prod1;
+        reg_sum    <= nxt_sum;  -- sum
+        reg_result <= nxt_result;  -- result sum after optional rounding
+      end if;
+    end if;
+  end process;
+
+  ------------------------------------------------------------------------------
+  -- Inputs
+  ------------------------------------------------------------------------------
+
+  nxt_a0 <= signed(in_a(  g_in_a_w - 1 downto 0));
+  nxt_b0 <= signed(in_b(  g_in_b_w - 1 downto 0));
+  nxt_a1 <= signed(in_a(2 * g_in_a_w - 1 downto g_in_a_w));
+  nxt_b1 <= signed(in_b(2 * g_in_b_w - 1 downto g_in_b_w));
+
+  no_input_reg : if g_pipeline_input = 0 generate  -- wired
+    a0 <= nxt_a0;
+    b0 <= nxt_b0;
+    a1 <= nxt_a1;
+    b1 <= nxt_b1;
+  end generate;
+
+  gen_input_reg : if g_pipeline_input > 0 generate  -- register input
+    a0 <= reg_a0;
+    b0 <= reg_b0;
+    a1 <= reg_a1;
+    b1 <= reg_b1;
+  end generate;
+
+  ------------------------------------------------------------------------------
+  -- Products
+  ------------------------------------------------------------------------------
+
+  nxt_prod0 <= a0 * b0;
+  nxt_prod1 <= a1 * b1;
+
+  no_product_reg : if g_pipeline_product = 0 generate  -- wired
+    prod0 <= nxt_prod0;
+    prod1 <= nxt_prod1;
+  end generate;
+  gen_product_reg : if g_pipeline_product > 0 generate  -- register
+    prod0 <= reg_prod0;
+    prod1 <= reg_prod1;
+  end generate;
+
+  ------------------------------------------------------------------------------
+  -- Sum
+  ------------------------------------------------------------------------------
+  gen_add : if g_add_sub = "ADD" generate
+    nxt_sum <= RESIZE_NUM(prod0, c_sum_w) + prod1;
+  end generate;
+
+  gen_sub : if g_add_sub = "SUB" generate
+    nxt_sum <= RESIZE_NUM(prod0, c_sum_w) - prod1;
+  end generate;
+
+  no_adder_reg : if g_pipeline_adder = 0 generate  -- wired
+    sum <= nxt_sum;
+  end generate;
+  gen_adder_reg : if g_pipeline_adder > 0 generate  -- register
+    sum <= reg_sum;
+  end generate;
+
+  ------------------------------------------------------------------------------
+  -- Result sum after optional rounding
+  ------------------------------------------------------------------------------
+
+  nxt_result <= RESIZE_NUM(sum, g_res_w);
+
+  no_result_reg : if g_pipeline_output = 0 generate  -- wired
+    result <= nxt_result;
+  end generate;
+  gen_result_reg : if g_pipeline_output > 0 generate  -- register
+    result <= reg_result;
+  end generate;
+
+  res <= std_logic_vector(result);
+end str;
-- 
GitLab