Skip to content
Snippets Groups Projects
Commit d0f2b6ad authored by David Brouwer's avatar David Brouwer
Browse files

Copied from ip_arria10_e2sg/mult_add2/ip_arria10_e2sg_mult_add2_rtl.vhd....

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.
parent c0942b9c
No related branches found
No related tags found
1 merge request!361Porting multipliers: mult, mult_add2, mult_add4, complex_mult, complex_mult_rtl, complex_mult_rtl_canonical for Intel Agilex 7
-------------------------------------------------------------------------------
--
-- 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;
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment