Skip to content
Snippets Groups Projects
Commit a2e24900 authored by Eric Kooistra's avatar Eric Kooistra
Browse files

Merge branch 'L2SDP-494' into 'master'

L2SDP-494

Closes L2SDP-494

See merge request desp/hdl!147
parents aec7a6be 77faa327
No related branches found
No related tags found
1 merge request!147L2SDP-494
Showing
with 1638 additions and 307 deletions
......@@ -18,10 +18,11 @@ test_bench_files =
tb/vhdl/tb_common_complex_mult.vhd
tb/vhdl/tb_tb_common_mult.vhd
tb/vhdl/tb_tb_common_complex_mult.vhd
regression_test_vhdl =
tb/vhdl/tb_common_mult_add2.vhd
tb/vhdl/tb_common_complex_mult.vhd
tb/vhdl/tb_tb_common_complex_mult.vhd
tb/vhdl/tb_tb_common_mult.vhd
......
......@@ -47,8 +47,6 @@ USE technology_lib.technology_select_pkg.ALL;
ENTITY common_complex_mult IS
GENERIC (
g_sim : BOOLEAN := FALSE;
g_sim_level : NATURAL := 0; -- 0: Simulate variant passed via g_variant for given g_technology
g_technology : NATURAL := c_tech_select_default;
g_variant : STRING := "IP";
g_in_a_w : POSITIVE;
......@@ -111,8 +109,6 @@ BEGIN
u_complex_mult : ENTITY tech_mult_lib.tech_complex_mult
GENERIC MAP(
g_sim => g_sim,
g_sim_level => g_sim_level,
g_technology => g_technology,
g_variant => g_variant,
g_in_a_w => g_in_a_w,
......
......@@ -23,7 +23,7 @@
-- p_verify verifies that the instances of common_complex_mult all yield the
-- expected results and ASSERTs an ERROR in case they differ.
-- Usage:
-- > as 10
-- > as 12
-- > run -all -- signal tb_end will stop the simulation by stopping the clk
LIBRARY IEEE, common_lib, technology_lib, tech_mult_lib, ip_stratixiv_mult_lib;
......@@ -32,14 +32,15 @@ USE IEEE.numeric_std.ALL;
USE technology_lib.technology_select_pkg.ALL;
USE common_lib.common_pkg.ALL;
USE common_lib.common_lfsr_sequences_pkg.ALL;
USE common_lib.common_str_pkg.ALL;
USE common_lib.tb_common_pkg.ALL;
ENTITY tb_common_complex_mult IS
GENERIC (
g_in_dat_w : NATURAL := 4;
g_out_dat_w : NATURAL := 8; -- g_in_dat_w*2 for multiply and +1 for adder
g_conjugate_b : BOOLEAN := FALSE; -- When FALSE p = a * b, else p = a * conj(b)
g_variant : STRING := "IP"; -- "RTL" or "IP"
g_in_dat_w : NATURAL := 18;
g_conjugate_b : BOOLEAN := TRUE; -- When FALSE p = a * b, else p = a * conj(b)
g_pipeline_input : NATURAL := 1;
g_pipeline_product : NATURAL := 0;
g_pipeline_adder : NATURAL := 1;
......@@ -53,9 +54,14 @@ ARCHITECTURE tb OF tb_common_complex_mult IS
CONSTANT clk_period : TIME := 10 ns;
CONSTANT c_pipeline : NATURAL := g_pipeline_input + g_pipeline_product + g_pipeline_adder + g_pipeline_output;
-- g_in_dat_w*2 for multiply and +1 for adder to fit largest im product value
CONSTANT c_out_dat_w : NATURAL := g_in_dat_w * 2 + 1;
CONSTANT c_max : INTEGER := 2**(g_in_dat_w-1)-1;
CONSTANT c_min : INTEGER := -2**(g_in_dat_w-1);
CONSTANT c_small : INTEGER := smallest(5, c_max);
CONSTANT c_technology : NATURAL := c_tech_select_default;
SIGNAL tb_end : STD_LOGIC := '0';
......@@ -64,25 +70,32 @@ ARCHITECTURE tb OF tb_common_complex_mult IS
SIGNAL random : STD_LOGIC_VECTOR(14 DOWNTO 0) := (OTHERS=>'0'); -- use different lengths to have different random sequences
-- Input
SIGNAL in_ar : STD_LOGIC_VECTOR(g_in_dat_w-1 DOWNTO 0);
SIGNAL in_ai : STD_LOGIC_VECTOR(g_in_dat_w-1 DOWNTO 0);
SIGNAL in_br : STD_LOGIC_VECTOR(g_in_dat_w-1 DOWNTO 0);
SIGNAL in_bi : STD_LOGIC_VECTOR(g_in_dat_w-1 DOWNTO 0);
SIGNAL in_val : STD_LOGIC; -- in_val is only passed on to out_val
SIGNAL result_val_expected : STD_LOGIC;
SIGNAL result_val_rtl : STD_LOGIC;
SIGNAL result_val_ip : STD_LOGIC;
SIGNAL out_result_re : STD_LOGIC_VECTOR(g_out_dat_w-1 DOWNTO 0); -- combinatorial result
SIGNAL out_result_im : STD_LOGIC_VECTOR(g_out_dat_w-1 DOWNTO 0);
SIGNAL result_re_expected : STD_LOGIC_VECTOR(g_out_dat_w-1 DOWNTO 0); -- pipelined results
SIGNAL result_re_rtl : STD_LOGIC_VECTOR(g_out_dat_w-1 DOWNTO 0);
SIGNAL result_re_ip : STD_LOGIC_VECTOR(g_out_dat_w-1 DOWNTO 0);
SIGNAL result_im_expected : STD_LOGIC_VECTOR(g_out_dat_w-1 DOWNTO 0);
SIGNAL result_im_rtl : STD_LOGIC_VECTOR(g_out_dat_w-1 DOWNTO 0);
SIGNAL result_im_ip : STD_LOGIC_VECTOR(g_out_dat_w-1 DOWNTO 0);
SIGNAL in_val : STD_LOGIC; -- in_val is only passed on to out_val, not used by multiplier itself
-- Results
-- . expected valid and DUT valid, only depends on in_val and c_pipeline
SIGNAL result_val_expected : STD_LOGIC;
SIGNAL result_val_dut : STD_LOGIC;
-- . product result
SIGNAL ref_result_re : STD_LOGIC_VECTOR(c_out_dat_w-1 DOWNTO 0); -- combinatorial result
SIGNAL ref_result_im : STD_LOGIC_VECTOR(c_out_dat_w-1 DOWNTO 0);
SIGNAL result_re_expected : STD_LOGIC_VECTOR(c_out_dat_w-1 DOWNTO 0); -- pipelined results
SIGNAL result_re_dut : STD_LOGIC_VECTOR(c_out_dat_w-1 DOWNTO 0);
SIGNAL result_im_expected : STD_LOGIC_VECTOR(c_out_dat_w-1 DOWNTO 0);
SIGNAL result_im_dut : STD_LOGIC_VECTOR(c_out_dat_w-1 DOWNTO 0);
-- Debug signals to view constant values in wave window
SIGNAL dbg_variant : STRING(g_variant'RANGE) := g_variant;
SIGNAL dbg_in_dat_w : NATURAL := g_in_dat_w;
SIGNAL dbg_conjugate_b : BOOLEAN := g_conjugate_b;
SIGNAL dbg_pipeline : NATURAL := c_pipeline;
BEGIN
......@@ -101,34 +114,36 @@ BEGIN
in_ai <= TO_SVEC(0, g_in_dat_w);
in_bi <= TO_SVEC(0, g_in_dat_w);
WAIT UNTIL rising_edge(clk);
FOR I IN 0 TO 9 LOOP
WAIT UNTIL rising_edge(clk);
END LOOP;
proc_common_wait_some_cycles(clk, 10);
rst <= '0';
FOR I IN 0 TO 9 LOOP
WAIT UNTIL rising_edge(clk);
END LOOP;
proc_common_wait_some_cycles(clk, 10);
-- Some special combinations
in_ar <= TO_SVEC(2, g_in_dat_w);
in_ai <= TO_SVEC(4, g_in_dat_w);
in_br <= TO_SVEC(3, g_in_dat_w);
in_bi <= TO_SVEC(5, g_in_dat_w);
WAIT UNTIL rising_edge(clk);
-- Some more special combinations with max and min
in_ar <= TO_SVEC( c_max, g_in_dat_w); -- p*p - p*p + j ( p*p + p*p) = 0 + j 2pp or p*p + p*p + j (-p*p + p*p) = 2pp + j 0
in_ai <= TO_SVEC( c_max, g_in_dat_w);
in_br <= TO_SVEC( c_max, g_in_dat_w);
in_bi <= TO_SVEC( c_max, g_in_dat_w);
WAIT UNTIL rising_edge(clk);
in_ar <= TO_SVEC( c_min, g_in_dat_w);
in_ai <= TO_SVEC( c_min, g_in_dat_w);
in_br <= TO_SVEC( c_min, g_in_dat_w);
in_bi <= TO_SVEC( c_min, g_in_dat_w);
WAIT UNTIL rising_edge(clk);
in_ar <= TO_SVEC( c_max, g_in_dat_w);
in_ai <= TO_SVEC( c_max, g_in_dat_w);
in_br <= TO_SVEC( c_min, g_in_dat_w);
in_bi <= TO_SVEC( c_min, g_in_dat_w);
-- Skip (c_min + j*c_min) * (c_min + j*c_min), because that just does not fit in 2*g_in_dat_w bits of complex multiplier
--in_ar <= TO_SVEC( c_min, g_in_dat_w);
--in_ai <= TO_SVEC( c_min, g_in_dat_w);
--in_br <= TO_SVEC( c_min, g_in_dat_w);
--in_bi <= TO_SVEC( c_min, g_in_dat_w);
--WAIT UNTIL rising_edge(clk);
IF dbg_conjugate_b = FALSE THEN
in_ar <= TO_SVEC( c_max, g_in_dat_w);
in_ai <= TO_SVEC( c_max, g_in_dat_w);
in_br <= TO_SVEC( c_min, g_in_dat_w);
in_bi <= TO_SVEC( c_min, g_in_dat_w);
ELSE
in_ar <= TO_SVEC( c_min, g_in_dat_w);
in_ai <= TO_SVEC( c_min, g_in_dat_w);
in_br <= TO_SVEC( c_max, g_in_dat_w);
in_bi <= TO_SVEC( c_max, g_in_dat_w);
END IF;
WAIT UNTIL rising_edge(clk);
in_ar <= TO_SVEC( c_max, g_in_dat_w);
in_ai <= TO_SVEC( c_max, g_in_dat_w);
......@@ -140,51 +155,85 @@ BEGIN
in_br <= TO_SVEC(-c_max, g_in_dat_w);
in_bi <= TO_SVEC(-c_max, g_in_dat_w);
WAIT UNTIL rising_edge(clk);
in_ar <= TO_SVEC(0, g_in_dat_w);
in_br <= TO_SVEC(0, g_in_dat_w);
in_ai <= TO_SVEC(0, g_in_dat_w);
in_bi <= TO_SVEC(0, g_in_dat_w);
WAIT UNTIL rising_edge(clk);
proc_common_wait_some_cycles(clk, 10);
FOR I IN 0 TO 49 LOOP
WAIT UNTIL rising_edge(clk);
END LOOP;
-- Some special combinations close to max, min
in_ar <= TO_SVEC( c_max, g_in_dat_w);
in_ai <= TO_SVEC( c_max-1, g_in_dat_w);
in_br <= TO_SVEC( c_max-2, g_in_dat_w);
in_bi <= TO_SVEC( c_max-3, g_in_dat_w);
WAIT UNTIL rising_edge(clk);
in_ar <= TO_SVEC( c_min, g_in_dat_w);
in_ai <= TO_SVEC( c_min+1, g_in_dat_w);
in_br <= TO_SVEC( c_min+2, g_in_dat_w);
in_bi <= TO_SVEC( c_min+3, g_in_dat_w);
WAIT UNTIL rising_edge(clk);
in_ar <= TO_SVEC( c_max, g_in_dat_w);
in_ai <= TO_SVEC( c_max-1, g_in_dat_w);
in_br <= TO_SVEC( c_min+2, g_in_dat_w);
in_bi <= TO_SVEC( c_min+3, g_in_dat_w);
WAIT UNTIL rising_edge(clk);
in_ar <= TO_SVEC( c_max, g_in_dat_w);
in_ai <= TO_SVEC( c_max-1, g_in_dat_w);
in_br <= TO_SVEC(-c_max+2, g_in_dat_w);
in_bi <= TO_SVEC(-c_max+3, g_in_dat_w);
WAIT UNTIL rising_edge(clk);
in_ar <= TO_SVEC( c_min, g_in_dat_w);
in_ai <= TO_SVEC( c_min+1, g_in_dat_w);
in_br <= TO_SVEC(-c_max+2, g_in_dat_w);
in_bi <= TO_SVEC(-c_max+3, g_in_dat_w);
WAIT UNTIL rising_edge(clk);
in_ar <= TO_SVEC(0, g_in_dat_w);
in_br <= TO_SVEC(0, g_in_dat_w);
in_ai <= TO_SVEC(0, g_in_dat_w);
in_bi <= TO_SVEC(0, g_in_dat_w);
WAIT UNTIL rising_edge(clk);
proc_common_wait_some_cycles(clk, 100);
-- All combinations
FOR I IN -c_max TO c_max LOOP
FOR J IN -c_max TO c_max LOOP
FOR K IN -c_max TO c_max LOOP
FOR L IN -c_max TO c_max LOOP
-- Try all small combinations
FOR I IN -c_small TO c_small LOOP
FOR J IN -c_small TO c_small LOOP
FOR K IN -c_small TO c_small LOOP
FOR L IN -c_small TO c_small LOOP
in_ar <= TO_SVEC(I, g_in_dat_w);
in_ai <= TO_SVEC(K, g_in_dat_w);
in_br <= TO_SVEC(J, g_in_dat_w);
in_bi <= TO_SVEC(L, g_in_dat_w);
WAIT UNTIL rising_edge(clk);
END LOOP;
proc_common_wait_some_cycles(clk, 10);
END LOOP;
proc_common_wait_some_cycles(clk, 100);
END LOOP;
END LOOP;
FOR I IN 0 TO 49 LOOP
WAIT UNTIL rising_edge(clk);
proc_common_wait_some_cycles(clk, 1000);
END LOOP;
tb_end <= '1';
WAIT;
END PROCESS;
-- Expected combinatorial complex multiply out_result
out_result_re <= func_complex_multiply(in_ar, in_ai, in_br, in_bi, g_conjugate_b, "RE", g_out_dat_w);
out_result_im <= func_complex_multiply(in_ar, in_ai, in_br, in_bi, g_conjugate_b, "IM", g_out_dat_w);
-- Expected combinatorial complex multiply ref_result
ref_result_re <= func_complex_multiply(in_ar, in_ai, in_br, in_bi, g_conjugate_b, "RE", c_out_dat_w);
ref_result_im <= func_complex_multiply(in_ar, in_ai, in_br, in_bi, g_conjugate_b, "IM", c_out_dat_w);
u_result_re : ENTITY common_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
g_in_dat_w => c_out_dat_w,
g_out_dat_w => c_out_dat_w
)
PORT MAP (
rst => rst,
clk => clk,
clken => '1',
in_dat => out_result_re,
in_dat => ref_result_re,
out_dat => result_re_expected
);
......@@ -193,14 +242,14 @@ BEGIN
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
g_in_dat_w => c_out_dat_w,
g_out_dat_w => c_out_dat_w
)
PORT MAP (
rst => rst,
clk => clk,
clken => '1',
in_dat => out_result_im,
in_dat => ref_result_im,
out_dat => result_im_expected
);
......@@ -217,40 +266,13 @@ BEGIN
out_dat => result_val_expected
);
u_dut_rtl : ENTITY work.common_complex_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_conjugate_b => g_conjugate_b,
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 => '1',
in_ar => in_ar,
in_ai => in_ai,
in_br => in_br,
in_bi => in_bi,
in_val => in_val,
out_pr => result_re_rtl,
out_pi => result_im_rtl,
out_val => result_val_rtl
);
u_dut_ip : ENTITY work.common_complex_mult
u_dut : ENTITY work.common_complex_mult
GENERIC MAP (
g_technology => c_technology,
g_variant => "IP",
g_variant => g_variant,
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_out_p_w => c_out_dat_w,
g_conjugate_b => g_conjugate_b,
g_pipeline_input => g_pipeline_input,
g_pipeline_product => g_pipeline_product,
......@@ -266,23 +288,18 @@ BEGIN
in_br => in_br,
in_bi => in_bi,
in_val => in_val,
out_pr => result_re_ip,
out_pi => result_im_ip,
out_val => result_val_ip
out_pr => result_re_dut,
out_pi => result_im_dut,
out_val => result_val_dut
);
p_verify : PROCESS(rst, clk)
BEGIN
IF rst='0' THEN
IF rising_edge(clk) THEN
ASSERT result_re_rtl = result_re_expected REPORT "Error: RE wrong RTL result" SEVERITY ERROR;
ASSERT result_im_rtl = result_im_expected REPORT "Error: IM wrong RTL result" SEVERITY ERROR;
ASSERT result_val_rtl = result_val_expected REPORT "Error: VAL wrong RTL result" SEVERITY ERROR;
ASSERT result_re_ip = result_re_expected REPORT "Error: RE wrong IP result" SEVERITY ERROR;
ASSERT result_im_ip = result_im_expected REPORT "Error: IM wrong IP result" SEVERITY ERROR;
ASSERT result_val_ip = result_val_expected REPORT "Error: VAL wrong IP result" SEVERITY ERROR;
ASSERT result_re_dut = result_re_expected REPORT "Error: RE wrong result, " & slv_to_str(result_re_dut) & " /= " & slv_to_str(result_re_expected) SEVERITY ERROR;
ASSERT result_im_dut = result_im_expected REPORT "Error: IM wrong result, " & slv_to_str(result_im_dut) & " /= " & slv_to_str(result_im_expected) SEVERITY ERROR;
ASSERT result_val_dut = result_val_expected REPORT "Error: VAL wrong result" SEVERITY ERROR;
END IF;
END IF;
END PROCESS;
......
-- --------------------------------------------------------------------------
-- Copyright 2020
-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
-- --------------------------------------------------------------------------
-- --------------------------------------------------------------------------
-- Author: E. Kooistra
-- Purpose: Multi tb for variants of common_complex_mult
-- Description:
-- Usage:
-- > as 3
-- > run -all
-- --------------------------------------------------------------------------
LIBRARY IEEE, technology_lib;
USE IEEE.std_logic_1164.ALL;
USE technology_lib.technology_pkg.ALL;
USE technology_lib.technology_select_pkg.ALL;
ENTITY tb_tb_common_complex_mult IS
END tb_tb_common_complex_mult;
ARCHITECTURE tb OF tb_tb_common_complex_mult IS
SIGNAL tb_end : STD_LOGIC := '0'; -- declare tb_end to avoid 'No objects found' error on 'when -label tb_end'
BEGIN
-- g_variant : STRING := "IP";
-- g_in_dat_w : NATURAL := 4;
-- g_conjugate_b : BOOLEAN := FALSE; -- When FALSE p = a * b, else p = a * conj(b)
-- g_pipeline_input : NATURAL := 1;
-- g_pipeline_product : NATURAL := 0;
-- g_pipeline_adder : NATURAL := 1;
-- g_pipeline_output : NATURAL := 1
-- IP variants
u_ip_18b : ENTITY work.tb_common_complex_mult GENERIC MAP ("IP", 18, FALSE, 1, 0, 1, 1);
u_ip_18b_conj : ENTITY work.tb_common_complex_mult GENERIC MAP ("IP", 18, TRUE, 1, 0, 1, 1);
gen_27b : IF c_tech_select_default /= c_tech_stratixiv GENERATE
u_ip_27b : ENTITY work.tb_common_complex_mult GENERIC MAP ("IP", 27, FALSE, 1, 0, 1, 1);
u_ip_27b_conj : ENTITY work.tb_common_complex_mult GENERIC MAP ("IP", 27, TRUE, 1, 0, 1, 1);
END GENERATE;
-- RTL variants
u_rtl_18b : ENTITY work.tb_common_complex_mult GENERIC MAP ("RTL", 18, FALSE, 1, 0, 1, 1);
u_rtl_27b : ENTITY work.tb_common_complex_mult GENERIC MAP ("RTL", 27, FALSE, 1, 0, 1, 1);
u_rtl_18b_conj : ENTITY work.tb_common_complex_mult GENERIC MAP ("RTL", 18, TRUE, 1, 0, 1, 1);
u_rtl_27b_conj : ENTITY work.tb_common_complex_mult GENERIC MAP ("RTL", 27, TRUE, 1, 0, 1, 1);
END tb;
......@@ -240,8 +240,6 @@ BEGIN
gen_nof_streams : FOR I IN 0 TO g_nof_streams-1 GENERATE
u_common_complex_mult : ENTITY common_mult_lib.common_complex_mult
GENERIC MAP (
g_sim => FALSE,
g_sim_level => 0, -- 0: Simulate variant passed via g_variant for given g_technology
g_technology => g_technology,
g_variant => "IP",
g_in_a_w => g_gain_w,
......
......@@ -181,7 +181,6 @@ BEGIN
------------------------------------------------------------------------------
-- u_CmplxMul_xx : ENTITY common_mult_lib.common_complex_mult
-- GENERIC MAP (
-- g_sim => g_sim,
-- g_technology => g_technology,
-- g_in_a_w => g_in_data_w,
-- g_in_b_w => g_in_data_w,
......@@ -203,7 +202,6 @@ BEGIN
u_CmplxMul_xy : ENTITY common_mult_lib.common_complex_mult
GENERIC MAP (
g_sim => g_sim,
g_technology => g_technology,
g_variant => g_variant,
g_in_a_w => g_in_data_w,
......@@ -226,7 +224,6 @@ BEGIN
u_CmplxMul_xxyy : ENTITY common_mult_lib.common_complex_mult
GENERIC MAP (
g_sim => g_sim,
g_technology => g_technology,
g_variant => g_variant,
g_in_a_w => g_in_data_w,
......
......@@ -34,3 +34,6 @@ set IP_DIR "$env(RADIOHDL_BUILD_DIR)/$env(BUILDSET)/qsys-generate/ip_arria10_e
vmap altmult_complex_180 ./work/
vcom "$IP_DIR/../altmult_complex_180/sim/ip_arria10_e1sg_complex_mult_altmult_complex_180_nkpx3mi.vhd"
set IP_DIR "$env(RADIOHDL_BUILD_DIR)/$env(BUILDSET)/qsys-generate/ip_arria10_e1sg_complex_mult_27b/sim"
vcom "$IP_DIR/../altmult_complex_180/sim/ip_arria10_e1sg_complex_mult_27b_altmult_complex_180_ylvsosy.vhd"
......@@ -31,3 +31,6 @@
set IP_DIR "$env(RADIOHDL_BUILD_DIR)/$env(BUILDSET)/qsys-generate/ip_arria10_e1sg_complex_mult/sim"
vcom "$IP_DIR/ip_arria10_e1sg_complex_mult.vhd"
set IP_DIR "$env(RADIOHDL_BUILD_DIR)/$env(BUILDSET)/qsys-generate/ip_arria10_e1sg_complex_mult_27b/sim"
vcom "$IP_DIR/ip_arria10_e1sg_complex_mult_27b.vhd"
......@@ -17,8 +17,10 @@ modelsim_compile_ip_files =
[quartus_project_file]
quartus_qip_files =
$RADIOHDL_BUILD_DIR/<buildset_name>/qsys-generate/ip_arria10_e1sg_complex_mult/ip_arria10_e1sg_complex_mult.qip
$RADIOHDL_BUILD_DIR/<buildset_name>/qsys-generate/ip_arria10_e1sg_complex_mult_27b/ip_arria10_e1sg_complex_mult_27b.qip
[generate_ip_libs]
qsys-generate_ip_files =
ip_arria10_e1sg_complex_mult.qsys
ip_arria10_e1sg_complex_mult_27b.ip
<?xml version="1.0" ?>
<spirit:component xmlns:altera="http://www.altera.com/XMLSchema/IPXact/extensions" xmlns:spirit="http://www.spiritconsortium.org/XMLSchema/SPIRIT/1685-2009">
<spirit:vendor>Intel Corporation</spirit:vendor>
<spirit:library>ip_arria10_e1sg_complex_mult_27b</spirit:library>
<spirit:name>altmult_complex_0</spirit:name>
<spirit:version>18.0</spirit:version>
<spirit:busInterfaces>
<spirit:busInterface>
<spirit:name>complex_input</spirit:name>
<spirit:busType spirit:vendor="altera" spirit:library="altera" spirit:name="conduit" spirit:version="18.0"></spirit:busType>
<spirit:slave></spirit:slave>
<spirit:portMaps>
<spirit:portMap>
<spirit:logicalPort>
<spirit:name>dataa_real</spirit:name>
</spirit:logicalPort>
<spirit:physicalPort>
<spirit:name>dataa_real</spirit:name>
</spirit:physicalPort>
</spirit:portMap>
<spirit:portMap>
<spirit:logicalPort>
<spirit:name>dataa_imag</spirit:name>
</spirit:logicalPort>
<spirit:physicalPort>
<spirit:name>dataa_imag</spirit:name>
</spirit:physicalPort>
</spirit:portMap>
<spirit:portMap>
<spirit:logicalPort>
<spirit:name>datab_real</spirit:name>
</spirit:logicalPort>
<spirit:physicalPort>
<spirit:name>datab_real</spirit:name>
</spirit:physicalPort>
</spirit:portMap>
<spirit:portMap>
<spirit:logicalPort>
<spirit:name>datab_imag</spirit:name>
</spirit:logicalPort>
<spirit:physicalPort>
<spirit:name>datab_imag</spirit:name>
</spirit:physicalPort>
</spirit:portMap>
<spirit:portMap>
<spirit:logicalPort>
<spirit:name>clk</spirit:name>
</spirit:logicalPort>
<spirit:physicalPort>
<spirit:name>clock</spirit:name>
</spirit:physicalPort>
</spirit:portMap>
<spirit:portMap>
<spirit:logicalPort>
<spirit:name>aclr</spirit:name>
</spirit:logicalPort>
<spirit:physicalPort>
<spirit:name>aclr</spirit:name>
</spirit:physicalPort>
</spirit:portMap>
<spirit:portMap>
<spirit:logicalPort>
<spirit:name>ena</spirit:name>
</spirit:logicalPort>
<spirit:physicalPort>
<spirit:name>ena</spirit:name>
</spirit:physicalPort>
</spirit:portMap>
</spirit:portMaps>
<spirit:parameters>
<spirit:parameter>
<spirit:name>associatedClock</spirit:name>
<spirit:displayName>associatedClock</spirit:displayName>
<spirit:value spirit:format="string" spirit:id="associatedClock"></spirit:value>
</spirit:parameter>
<spirit:parameter>
<spirit:name>associatedReset</spirit:name>
<spirit:displayName>associatedReset</spirit:displayName>
<spirit:value spirit:format="string" spirit:id="associatedReset"></spirit:value>
</spirit:parameter>
<spirit:parameter>
<spirit:name>prSafe</spirit:name>
<spirit:displayName>Partial Reconfiguration Safe</spirit:displayName>
<spirit:value spirit:format="bool" spirit:id="prSafe">false</spirit:value>
</spirit:parameter>
</spirit:parameters>
</spirit:busInterface>
<spirit:busInterface>
<spirit:name>complex_output</spirit:name>
<spirit:busType spirit:vendor="altera" spirit:library="altera" spirit:name="conduit" spirit:version="18.0"></spirit:busType>
<spirit:slave></spirit:slave>
<spirit:portMaps>
<spirit:portMap>
<spirit:logicalPort>
<spirit:name>result_real</spirit:name>
</spirit:logicalPort>
<spirit:physicalPort>
<spirit:name>result_real</spirit:name>
</spirit:physicalPort>
</spirit:portMap>
<spirit:portMap>
<spirit:logicalPort>
<spirit:name>result_imag</spirit:name>
</spirit:logicalPort>
<spirit:physicalPort>
<spirit:name>result_imag</spirit:name>
</spirit:physicalPort>
</spirit:portMap>
</spirit:portMaps>
<spirit:parameters>
<spirit:parameter>
<spirit:name>associatedClock</spirit:name>
<spirit:displayName>associatedClock</spirit:displayName>
<spirit:value spirit:format="string" spirit:id="associatedClock"></spirit:value>
</spirit:parameter>
<spirit:parameter>
<spirit:name>associatedReset</spirit:name>
<spirit:displayName>associatedReset</spirit:displayName>
<spirit:value spirit:format="string" spirit:id="associatedReset"></spirit:value>
</spirit:parameter>
<spirit:parameter>
<spirit:name>prSafe</spirit:name>
<spirit:displayName>Partial Reconfiguration Safe</spirit:displayName>
<spirit:value spirit:format="bool" spirit:id="prSafe">false</spirit:value>
</spirit:parameter>
</spirit:parameters>
<spirit:vendorExtensions>
<altera:altera_assignments>
<spirit:parameters>
<spirit:parameter>
<spirit:name>ui.blockdiagram.direction</spirit:name>
<spirit:value spirit:format="string" spirit:id="ui.blockdiagram.direction">output</spirit:value>
</spirit:parameter>
</spirit:parameters>
</altera:altera_assignments>
</spirit:vendorExtensions>
</spirit:busInterface>
</spirit:busInterfaces>
<spirit:model>
<spirit:views>
<spirit:view>
<spirit:name>QUARTUS_SYNTH</spirit:name>
<spirit:envIdentifier>:quartus.altera.com:</spirit:envIdentifier>
<spirit:modelName>altmult_complex</spirit:modelName>
<spirit:fileSetRef>
<spirit:localName>QUARTUS_SYNTH</spirit:localName>
</spirit:fileSetRef>
</spirit:view>
</spirit:views>
<spirit:ports>
<spirit:port>
<spirit:name>dataa_real</spirit:name>
<spirit:wire>
<spirit:direction>in</spirit:direction>
<spirit:vector>
<spirit:left>0</spirit:left>
<spirit:right>26</spirit:right>
</spirit:vector>
<spirit:wireTypeDefs>
<spirit:wireTypeDef>
<spirit:typeName>STD_LOGIC_VECTOR</spirit:typeName>
<spirit:viewNameRef>QUARTUS_SYNTH</spirit:viewNameRef>
</spirit:wireTypeDef>
</spirit:wireTypeDefs>
</spirit:wire>
</spirit:port>
<spirit:port>
<spirit:name>dataa_imag</spirit:name>
<spirit:wire>
<spirit:direction>in</spirit:direction>
<spirit:vector>
<spirit:left>0</spirit:left>
<spirit:right>26</spirit:right>
</spirit:vector>
<spirit:wireTypeDefs>
<spirit:wireTypeDef>
<spirit:typeName>STD_LOGIC_VECTOR</spirit:typeName>
<spirit:viewNameRef>QUARTUS_SYNTH</spirit:viewNameRef>
</spirit:wireTypeDef>
</spirit:wireTypeDefs>
</spirit:wire>
</spirit:port>
<spirit:port>
<spirit:name>datab_real</spirit:name>
<spirit:wire>
<spirit:direction>in</spirit:direction>
<spirit:vector>
<spirit:left>0</spirit:left>
<spirit:right>26</spirit:right>
</spirit:vector>
<spirit:wireTypeDefs>
<spirit:wireTypeDef>
<spirit:typeName>STD_LOGIC_VECTOR</spirit:typeName>
<spirit:viewNameRef>QUARTUS_SYNTH</spirit:viewNameRef>
</spirit:wireTypeDef>
</spirit:wireTypeDefs>
</spirit:wire>
</spirit:port>
<spirit:port>
<spirit:name>datab_imag</spirit:name>
<spirit:wire>
<spirit:direction>in</spirit:direction>
<spirit:vector>
<spirit:left>0</spirit:left>
<spirit:right>26</spirit:right>
</spirit:vector>
<spirit:wireTypeDefs>
<spirit:wireTypeDef>
<spirit:typeName>STD_LOGIC_VECTOR</spirit:typeName>
<spirit:viewNameRef>QUARTUS_SYNTH</spirit:viewNameRef>
</spirit:wireTypeDef>
</spirit:wireTypeDefs>
</spirit:wire>
</spirit:port>
<spirit:port>
<spirit:name>clock</spirit:name>
<spirit:wire>
<spirit:direction>in</spirit:direction>
<spirit:wireTypeDefs>
<spirit:wireTypeDef>
<spirit:typeName>STD_LOGIC</spirit:typeName>
<spirit:viewNameRef>QUARTUS_SYNTH</spirit:viewNameRef>
</spirit:wireTypeDef>
</spirit:wireTypeDefs>
</spirit:wire>
</spirit:port>
<spirit:port>
<spirit:name>aclr</spirit:name>
<spirit:wire>
<spirit:direction>in</spirit:direction>
<spirit:wireTypeDefs>
<spirit:wireTypeDef>
<spirit:typeName>STD_LOGIC</spirit:typeName>
<spirit:viewNameRef>QUARTUS_SYNTH</spirit:viewNameRef>
</spirit:wireTypeDef>
</spirit:wireTypeDefs>
</spirit:wire>
</spirit:port>
<spirit:port>
<spirit:name>ena</spirit:name>
<spirit:wire>
<spirit:direction>in</spirit:direction>
<spirit:wireTypeDefs>
<spirit:wireTypeDef>
<spirit:typeName>STD_LOGIC</spirit:typeName>
<spirit:viewNameRef>QUARTUS_SYNTH</spirit:viewNameRef>
</spirit:wireTypeDef>
</spirit:wireTypeDefs>
</spirit:wire>
</spirit:port>
<spirit:port>
<spirit:name>result_real</spirit:name>
<spirit:wire>
<spirit:direction>out</spirit:direction>
<spirit:vector>
<spirit:left>0</spirit:left>
<spirit:right>53</spirit:right>
</spirit:vector>
<spirit:wireTypeDefs>
<spirit:wireTypeDef>
<spirit:typeName>STD_LOGIC_VECTOR</spirit:typeName>
<spirit:viewNameRef>QUARTUS_SYNTH</spirit:viewNameRef>
</spirit:wireTypeDef>
</spirit:wireTypeDefs>
</spirit:wire>
</spirit:port>
<spirit:port>
<spirit:name>result_imag</spirit:name>
<spirit:wire>
<spirit:direction>out</spirit:direction>
<spirit:vector>
<spirit:left>0</spirit:left>
<spirit:right>53</spirit:right>
</spirit:vector>
<spirit:wireTypeDefs>
<spirit:wireTypeDef>
<spirit:typeName>STD_LOGIC_VECTOR</spirit:typeName>
<spirit:viewNameRef>QUARTUS_SYNTH</spirit:viewNameRef>
</spirit:wireTypeDef>
</spirit:wireTypeDefs>
</spirit:wire>
</spirit:port>
</spirit:ports>
</spirit:model>
<spirit:vendorExtensions>
<altera:entity_info>
<spirit:vendor>Intel Corporation</spirit:vendor>
<spirit:library>ip_arria10_e1sg_complex_mult_27b</spirit:library>
<spirit:name>altmult_complex</spirit:name>
<spirit:version>18.0</spirit:version>
</altera:entity_info>
<altera:altera_module_parameters>
<spirit:parameters>
<spirit:parameter>
<spirit:name>DEVICE_FAMILY</spirit:name>
<spirit:displayName>Device family</spirit:displayName>
<spirit:value spirit:format="string" spirit:id="DEVICE_FAMILY">Arria 10</spirit:value>
</spirit:parameter>
<spirit:parameter>
<spirit:name>CBX_AUTO_BLACKBOX</spirit:name>
<spirit:displayName>CBX_AUTO_BLACKBOX</spirit:displayName>
<spirit:value spirit:format="string" spirit:id="CBX_AUTO_BLACKBOX">ALL</spirit:value>
</spirit:parameter>
<spirit:parameter>
<spirit:name>WIDTH_A</spirit:name>
<spirit:displayName>How wide should the A input buses be?</spirit:displayName>
<spirit:value spirit:format="long" spirit:id="WIDTH_A">27</spirit:value>
</spirit:parameter>
<spirit:parameter>
<spirit:name>WIDTH_B</spirit:name>
<spirit:displayName>How wide should the B input buses be?</spirit:displayName>
<spirit:value spirit:format="long" spirit:id="WIDTH_B">27</spirit:value>
</spirit:parameter>
<spirit:parameter>
<spirit:name>WIDTH_RESULT</spirit:name>
<spirit:displayName>How wide should the 'result' output bus be?</spirit:displayName>
<spirit:value spirit:format="long" spirit:id="WIDTH_RESULT">54</spirit:value>
</spirit:parameter>
<spirit:parameter>
<spirit:name>REPRESENTATION_A</spirit:name>
<spirit:displayName>What is the representation format for A inputs?</spirit:displayName>
<spirit:value spirit:format="long" spirit:id="REPRESENTATION_A">1</spirit:value>
</spirit:parameter>
<spirit:parameter>
<spirit:name>REPRESENTATION_B</spirit:name>
<spirit:displayName>What is the representation format for B inputs?</spirit:displayName>
<spirit:value spirit:format="long" spirit:id="REPRESENTATION_B">1</spirit:value>
</spirit:parameter>
<spirit:parameter>
<spirit:name>GUI_DYNAMIC_COMPLEX</spirit:name>
<spirit:displayName>Dynamic Complex Mode</spirit:displayName>
<spirit:value spirit:format="bool" spirit:id="GUI_DYNAMIC_COMPLEX">false</spirit:value>
</spirit:parameter>
<spirit:parameter>
<spirit:name>IMPLEMENTATION_STYLE</spirit:name>
<spirit:displayName>Which implementation style should be used?</spirit:displayName>
<spirit:value spirit:format="string" spirit:id="IMPLEMENTATION_STYLE">AUTO</spirit:value>
</spirit:parameter>
<spirit:parameter>
<spirit:name>PIPELINE</spirit:name>
<spirit:displayName>Output latency</spirit:displayName>
<spirit:value spirit:format="long" spirit:id="PIPELINE">3</spirit:value>
</spirit:parameter>
<spirit:parameter>
<spirit:name>GUI_CLEAR_TYPE</spirit:name>
<spirit:displayName>Clear Signal Type</spirit:displayName>
<spirit:value spirit:format="string" spirit:id="GUI_CLEAR_TYPE">ACLR</spirit:value>
</spirit:parameter>
<spirit:parameter>
<spirit:name>GUI_USE_CLKEN</spirit:name>
<spirit:displayName>Create a Clock Enable input?</spirit:displayName>
<spirit:value spirit:format="bool" spirit:id="GUI_USE_CLKEN">true</spirit:value>
</spirit:parameter>
</spirit:parameters>
</altera:altera_module_parameters>
<altera:altera_system_parameters>
<spirit:parameters>
<spirit:parameter>
<spirit:name>device</spirit:name>
<spirit:displayName>Device</spirit:displayName>
<spirit:value spirit:format="string" spirit:id="device">10AX115S2F45E1SG</spirit:value>
</spirit:parameter>
<spirit:parameter>
<spirit:name>deviceFamily</spirit:name>
<spirit:displayName>Device family</spirit:displayName>
<spirit:value spirit:format="string" spirit:id="deviceFamily">Arria 10</spirit:value>
</spirit:parameter>
<spirit:parameter>
<spirit:name>deviceSpeedGrade</spirit:name>
<spirit:displayName>Device Speed Grade</spirit:displayName>
<spirit:value spirit:format="string" spirit:id="deviceSpeedGrade">1</spirit:value>
</spirit:parameter>
<spirit:parameter>
<spirit:name>generationId</spirit:name>
<spirit:displayName>Generation Id</spirit:displayName>
<spirit:value spirit:format="long" spirit:id="generationId">0</spirit:value>
</spirit:parameter>
<spirit:parameter>
<spirit:name>bonusData</spirit:name>
<spirit:displayName>bonusData</spirit:displayName>
<spirit:value spirit:format="string" spirit:id="bonusData">bonusData
{
element altmult_complex_0
{
datum _sortIndex
{
value = "0";
type = "int";
}
}
}
</spirit:value>
</spirit:parameter>
<spirit:parameter>
<spirit:name>hideFromIPCatalog</spirit:name>
<spirit:displayName>Hide from IP Catalog</spirit:displayName>
<spirit:value spirit:format="bool" spirit:id="hideFromIPCatalog">true</spirit:value>
</spirit:parameter>
<spirit:parameter>
<spirit:name>lockedInterfaceDefinition</spirit:name>
<spirit:displayName>lockedInterfaceDefinition</spirit:displayName>
<spirit:value spirit:format="string" spirit:id="lockedInterfaceDefinition"></spirit:value>
</spirit:parameter>
<spirit:parameter>
<spirit:name>systemInfos</spirit:name>
<spirit:displayName>systemInfos</spirit:displayName>
<spirit:value spirit:format="string" spirit:id="systemInfos"><![CDATA[<systemInfosDefinition>
<connPtSystemInfos/>
</systemInfosDefinition>]]></spirit:value>
</spirit:parameter>
</spirit:parameters>
</altera:altera_system_parameters>
<altera:altera_interface_boundary>
<altera:interface_mapping altera:name="complex_input" altera:internal="altmult_complex_0.complex_input" altera:type="conduit" altera:dir="end">
<altera:port_mapping altera:name="aclr" altera:internal="aclr"></altera:port_mapping>
<altera:port_mapping altera:name="clock" altera:internal="clock"></altera:port_mapping>
<altera:port_mapping altera:name="dataa_imag" altera:internal="dataa_imag"></altera:port_mapping>
<altera:port_mapping altera:name="dataa_real" altera:internal="dataa_real"></altera:port_mapping>
<altera:port_mapping altera:name="datab_imag" altera:internal="datab_imag"></altera:port_mapping>
<altera:port_mapping altera:name="datab_real" altera:internal="datab_real"></altera:port_mapping>
<altera:port_mapping altera:name="ena" altera:internal="ena"></altera:port_mapping>
</altera:interface_mapping>
<altera:interface_mapping altera:name="complex_output" altera:internal="altmult_complex_0.complex_output" altera:type="conduit" altera:dir="end">
<altera:port_mapping altera:name="result_imag" altera:internal="result_imag"></altera:port_mapping>
<altera:port_mapping altera:name="result_real" altera:internal="result_real"></altera:port_mapping>
</altera:interface_mapping>
</altera:altera_interface_boundary>
<altera:altera_has_warnings>false</altera:altera_has_warnings>
<altera:altera_has_errors>false</altera:altera_has_errors>
</spirit:vendorExtensions>
</spirit:component>
\ No newline at end of file
......@@ -34,3 +34,7 @@ set IP_DIR "$env(RADIOHDL_BUILD_DIR)/$env(BUILDSET)/qsys-generate/ip_arria10_e
vmap altmult_complex_1910 ./work/
vcom "$IP_DIR/../altmult_complex_1910/sim/ip_arria10_e2sg_complex_mult_altmult_complex_1910_cumkcni.vhd" -work altmult_complex_1910
set IP_DIR "$env(RADIOHDL_BUILD_DIR)/$env(BUILDSET)/qsys-generate/ip_arria10_e2sg_complex_mult_27b/sim"
vcom "$IP_DIR/../altmult_complex_1910/sim/ip_arria10_e2sg_complex_mult_27b_altmult_complex_1910_ecifj3y.vhd" -work altmult_complex_1910
......@@ -30,7 +30,8 @@
set IP_DIR "$env(RADIOHDL_BUILD_DIR)/$env(BUILDSET)/qsys-generate/ip_arria10_e2sg_complex_mult/sim"
vmap altmult_complex_1910 ./work/
vcom "$IP_DIR/../altmult_complex_1910/sim/ip_arria10_e2sg_complex_mult_altmult_complex_1910_cumkcni.vhd" -work altmult_complex_1910
vcom "$IP_DIR/ip_arria10_e2sg_complex_mult.vhd" -work altmult_complex_1910
vcom "$IP_DIR/ip_arria10_e2sg_complex_mult.vhd"
set IP_DIR "$env(RADIOHDL_BUILD_DIR)/$env(BUILDSET)/qsys-generate/ip_arria10_e2sg_complex_mult_27b/sim"
vcom "$IP_DIR/ip_arria10_e2sg_complex_mult_27b.vhd"
......@@ -17,8 +17,10 @@ modelsim_compile_ip_files =
[quartus_project_file]
quartus_qip_files =
$RADIOHDL_BUILD_DIR/<buildset_name>/qsys-generate/ip_arria10_e2sg_complex_mult/ip_arria10_e2sg_complex_mult.qip
$RADIOHDL_BUILD_DIR/<buildset_name>/qsys-generate/ip_arria10_e2sg_complex_mult_27b/ip_arria10_e2sg_complex_mult_27b.qip
[generate_ip_libs]
qsys-generate_ip_files =
ip_arria10_e2sg_complex_mult.ip
ip_arria10_e2sg_complex_mult_27b.ip
......@@ -18,6 +18,41 @@
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
-------------------------------------------------------------------------------
--
-- Author : E. Kooistra
-- Purpose : Wrapper for complex multiplier IP
-- Decription :
--
-- Calculate complex product:
--
-- (ar + j*ai) * (br + j*bi) = (ar*br - ai*bi) + j *(ar*bi + ai*br)
-- = pr + j * pi
--
-- Assume IP is generated for complex product width for pr, pi of:
--
-- c_dsp_prod_w = 2*c_dsp_dat_w.
--
-- It is not necessary to support product width 2*c_dsp_dat_w + 1,
-- because this +1 bit is only needed for pi in case ar = ai = br = bi
-- = min, where
--
-- min = -2**(c_dsp_dat_w-1)
-- max = 2**(c_dsp_dat_w-1) - 1.
--
-- The largest value for pi = min**2 + min**2.
-- The largest value for pr = min**2 - min*max < largest pi.
--
-- The largest pi = 2 * min**2 = 2**(c_dsp_dat_w-1), so it just does not
-- fit in c_dsp_prod_w, but largest pi - 1 = 2**(c_dsp_dat_w-1) - 1 does
-- fit, so all other input values fit. In DSP systems the input value
-- (min + j*min) typically never occurs.
--
-- Example: g_in_a_w = 3 bit:
-- --> min = -4
-- c_dsp_prod_w = 6
-- --> largest pi = 32
-- --> largest pi - 1 = 31 = 2**(c_dsp_prod_w-1) - 1
--
LIBRARY IEEE, common_lib, technology_lib;
USE IEEE.std_logic_1164.ALL;
......@@ -38,8 +73,6 @@ LIBRARY ip_arria10_complex_mult_rtl_canonical_lib;
ENTITY tech_complex_mult IS
GENERIC (
g_sim : BOOLEAN := TRUE;
g_sim_level : NATURAL := 0; -- 0: Simulate variant passed via g_variant for given g_technology
g_technology : NATURAL := c_tech_select_default;
g_variant : STRING := "IP";
g_in_a_w : POSITIVE;
......@@ -66,14 +99,8 @@ END tech_complex_mult;
ARCHITECTURE str of tech_complex_mult is
-- Force to maximum 18 bit width, because:
-- . the ip_stratixiv_complex_mult is generated for 18b inputs and 36b output and then uses 4 real multipliers and no additional registers
-- . if one input > 18b then another IP needs to be regenerated and that will use 8 real multipliers and some extra LUTs and registers
-- . if both inputs > 18b then another IP needs to be regenerated and that will use 16 real multipliers and some extra LUTs and registers
-- . if the output is set to 18b+18b + 1b =37b to account for the sum then another IP needs to be regenerated and that will use some extra registers
-- ==> for inputs <= 18b this ip_stratixiv_complex_mult is appropriate and it can not be made parametrisable to fit also inputs > 18b.
CONSTANT c_dsp_dat_w : NATURAL := 18;
CONSTANT c_dsp_prod_w : NATURAL := 2*c_dsp_dat_w;
CONSTANT c_dsp_dat_w : NATURAL := sel_a_b(g_in_a_w <= c_dsp_mult_18_w, c_dsp_mult_18_w, c_dsp_mult_27_w); -- g_in_a_w = g_in_b_w
CONSTANT c_dsp_prod_w : NATURAL := 2*c_dsp_dat_w;
SIGNAL ar : STD_LOGIC_VECTOR(c_dsp_dat_w-1 DOWNTO 0);
SIGNAL ai : STD_LOGIC_VECTOR(c_dsp_dat_w-1 DOWNTO 0);
......@@ -82,244 +109,253 @@ ARCHITECTURE str of tech_complex_mult is
SIGNAL mult_re : STD_LOGIC_VECTOR(c_dsp_prod_w-1 DOWNTO 0);
SIGNAL mult_im : STD_LOGIC_VECTOR(c_dsp_prod_w-1 DOWNTO 0);
-- sim_model=1
SIGNAL result_re_undelayed : STD_LOGIC_VECTOR(g_in_b_w+g_in_a_w-1 DOWNTO 0);
SIGNAL result_im_undelayed : STD_LOGIC_VECTOR(g_in_b_w+g_in_a_w-1 DOWNTO 0);
begin
BEGIN
gen_ip_stratixiv_ip : IF (g_sim=FALSE OR (g_sim=TRUE AND g_sim_level=0)) AND (g_technology=c_tech_stratixiv AND g_variant="IP") GENERATE
-----------------------------------------------------------------------------
-- IP variants for <= 18 bit
-----------------------------------------------------------------------------
gen_ip_stratixiv_ip : IF g_variant="IP" AND g_technology=c_tech_stratixiv AND c_dsp_dat_w <= c_dsp_mult_18_w GENERATE
-- Adapt DSP input widths
ar <= RESIZE_SVEC(in_ar, c_dsp_dat_w);
ai <= RESIZE_SVEC(in_ai, c_dsp_dat_w);
br <= RESIZE_SVEC(in_br, c_dsp_dat_w);
bi <= RESIZE_SVEC(in_bi, c_dsp_dat_w) WHEN g_conjugate_b=FALSE ELSE TO_SVEC(-TO_SINT(in_bi), c_dsp_dat_w);
ar <= RESIZE_SVEC(in_ar, c_dsp_mult_18_w);
ai <= RESIZE_SVEC(in_ai, c_dsp_mult_18_w);
br <= RESIZE_SVEC(in_br, c_dsp_mult_18_w);
bi <= RESIZE_SVEC(in_bi, c_dsp_mult_18_w) WHEN g_conjugate_b=FALSE ELSE TO_SVEC(-TO_SINT(in_bi), c_dsp_mult_18_w);
u0 : ip_stratixiv_complex_mult
PORT MAP (
aclr => rst,
clock => clk,
dataa_imag => ai,
dataa_real => ar,
datab_imag => bi,
datab_real => br,
ena => clken,
result_imag => mult_im,
result_real => mult_re
);
aclr => rst,
clock => clk,
dataa_imag => ai,
dataa_real => ar,
datab_imag => bi,
datab_real => br,
ena => clken,
result_imag => mult_im,
result_real => mult_re
);
-- Back to true input widths and then resize for output width
result_re <= RESIZE_SVEC(mult_re, g_out_p_w);
result_im <= RESIZE_SVEC(mult_im, g_out_p_w);
END GENERATE;
gen_ip_stratixiv_rtl : IF (g_sim=FALSE OR (g_sim=TRUE AND g_sim_level=0)) AND (g_technology=c_tech_stratixiv AND g_variant="RTL") GENERATE
u0 : ip_stratixiv_complex_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_conjugate_b => g_conjugate_b,
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_ip : IF (g_sim=FALSE OR (g_sim=TRUE AND g_sim_level=0)) AND (g_technology=c_tech_arria10 AND g_variant="IP") GENERATE
gen_ip_arria10_ip : IF g_variant="IP" AND g_technology=c_tech_arria10 AND c_dsp_dat_w <= c_dsp_mult_18_w GENERATE
-- Adapt DSP input widths
ar <= RESIZE_SVEC(in_ar, c_dsp_dat_w);
ai <= RESIZE_SVEC(in_ai, c_dsp_dat_w);
br <= RESIZE_SVEC(in_br, c_dsp_dat_w);
bi <= RESIZE_SVEC(in_bi, c_dsp_dat_w) WHEN g_conjugate_b=FALSE ELSE TO_SVEC(-TO_SINT(in_bi), c_dsp_dat_w);
ar <= RESIZE_SVEC(in_ar, c_dsp_mult_18_w);
ai <= RESIZE_SVEC(in_ai, c_dsp_mult_18_w);
br <= RESIZE_SVEC(in_br, c_dsp_mult_18_w);
bi <= RESIZE_SVEC(in_bi, c_dsp_mult_18_w) WHEN g_conjugate_b=FALSE ELSE TO_SVEC(-TO_SINT(in_bi), c_dsp_mult_18_w);
u0 : ip_arria10_complex_mult
PORT MAP (
aclr => rst,
clock => clk,
dataa_imag => ai,
dataa_real => ar,
datab_imag => bi,
datab_real => br,
ena => clken,
result_imag => mult_im,
result_real => mult_re
);
aclr => rst,
clock => clk,
dataa_imag => ai,
dataa_real => ar,
datab_imag => bi,
datab_real => br,
ena => clken,
result_imag => mult_im,
result_real => mult_re
);
-- Back to true input widths and then resize for output width
result_re <= RESIZE_SVEC(mult_re, g_out_p_w);
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 OR g_technology=c_tech_arria10_e2sg) AND g_variant="RTL") GENERATE
u0 : ip_arria10_complex_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_conjugate_b => g_conjugate_b,
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
gen_ip_arria10_e1sg_ip : IF g_variant="IP" AND g_technology=c_tech_arria10_e1sg AND c_dsp_dat_w <= c_dsp_mult_18_w GENERATE
-- Adapt DSP input widths
ar <= RESIZE_SVEC(in_ar, c_dsp_mult_18_w);
ai <= RESIZE_SVEC(in_ai, c_dsp_mult_18_w);
br <= RESIZE_SVEC(in_br, c_dsp_mult_18_w);
bi <= RESIZE_SVEC(in_bi, c_dsp_mult_18_w) WHEN g_conjugate_b=FALSE ELSE TO_SVEC(-TO_SINT(in_bi), c_dsp_mult_18_w);
u0 : ip_arria10_e1sg_complex_mult
PORT MAP (
aclr => rst,
clock => clk,
dataa_imag => ai,
dataa_real => ar,
datab_imag => bi,
datab_real => br,
ena => clken,
result_imag => mult_im,
result_real => mult_re
);
-- Back to true input widths and then resize for output width
result_re <= RESIZE_SVEC(mult_re, g_out_p_w);
result_im <= RESIZE_SVEC(mult_im, g_out_p_w);
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 OR g_technology=c_tech_arria10_e2sg) 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
gen_ip_arria10_e2sg_ip : IF g_variant="IP" AND g_technology=c_tech_arria10_e2sg AND c_dsp_dat_w <= c_dsp_mult_18_w GENERATE
-- Adapt DSP input widths
ar <= RESIZE_SVEC(in_ar, c_dsp_mult_18_w);
ai <= RESIZE_SVEC(in_ai, c_dsp_mult_18_w);
br <= RESIZE_SVEC(in_br, c_dsp_mult_18_w);
bi <= RESIZE_SVEC(in_bi, c_dsp_mult_18_w) WHEN g_conjugate_b=FALSE ELSE TO_SVEC(-TO_SINT(in_bi), c_dsp_mult_18_w);
u0 : ip_arria10_e2sg_complex_mult
PORT MAP (
aclr => rst,
clock => clk,
dataa_imag => ai,
dataa_real => ar,
datab_imag => bi,
datab_real => br,
ena => clken,
result_imag => mult_im,
result_real => mult_re
);
-- Back to true input widths and then resize for output width
result_re <= RESIZE_SVEC(mult_re, g_out_p_w);
result_im <= RESIZE_SVEC(mult_im, g_out_p_w);
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
-----------------------------------------------------------------------------
-- IP variants for > 18 bit and <= 27 bit
-----------------------------------------------------------------------------
gen_ip_arria10_e1sg_ip_27b : IF g_variant="IP" AND g_technology=c_tech_arria10_e1sg AND c_dsp_dat_w > c_dsp_mult_18_w AND c_dsp_dat_w <= c_dsp_mult_27_w GENERATE
-- Adapt DSP input widths
ar <= RESIZE_SVEC(in_ar, c_dsp_dat_w);
ai <= RESIZE_SVEC(in_ai, c_dsp_dat_w);
br <= RESIZE_SVEC(in_br, c_dsp_dat_w);
bi <= RESIZE_SVEC(in_bi, c_dsp_dat_w) WHEN g_conjugate_b=FALSE ELSE TO_SVEC(-TO_SINT(in_bi), c_dsp_dat_w);
ar <= RESIZE_SVEC(in_ar, c_dsp_mult_27_w);
ai <= RESIZE_SVEC(in_ai, c_dsp_mult_27_w);
br <= RESIZE_SVEC(in_br, c_dsp_mult_27_w);
bi <= RESIZE_SVEC(in_bi, c_dsp_mult_27_w) WHEN g_conjugate_b=FALSE ELSE TO_SVEC(-TO_SINT(in_bi), c_dsp_mult_27_w);
u0 : ip_arria10_e1sg_complex_mult
u0 : ip_arria10_e1sg_complex_mult_27b
PORT MAP (
aclr => rst,
clock => clk,
dataa_imag => ai,
dataa_real => ar,
datab_imag => bi,
datab_real => br,
ena => clken,
result_imag => mult_im,
result_real => mult_re
);
aclr => rst,
clock => clk,
dataa_imag => ai,
dataa_real => ar,
datab_imag => bi,
datab_real => br,
ena => clken,
result_imag => mult_im,
result_real => mult_re
);
-- Back to true input widths and then resize for output width
result_re <= RESIZE_SVEC(mult_re, g_out_p_w);
result_im <= RESIZE_SVEC(mult_im, g_out_p_w);
END GENERATE;
gen_ip_arria10_e2sg_ip : IF (g_sim=FALSE OR (g_sim=TRUE AND g_sim_level=0)) AND (g_technology=c_tech_arria10_e2sg AND g_variant="IP") GENERATE
gen_ip_arria10_e2sg_ip_27b : IF g_variant="IP" AND g_technology=c_tech_arria10_e2sg AND c_dsp_dat_w > c_dsp_mult_18_w AND c_dsp_dat_w <= c_dsp_mult_27_w GENERATE
-- Adapt DSP input widths
ar <= RESIZE_SVEC(in_ar, c_dsp_dat_w);
ai <= RESIZE_SVEC(in_ai, c_dsp_dat_w);
br <= RESIZE_SVEC(in_br, c_dsp_dat_w);
bi <= RESIZE_SVEC(in_bi, c_dsp_dat_w) WHEN g_conjugate_b=FALSE ELSE TO_SVEC(-TO_SINT(in_bi), c_dsp_dat_w);
ar <= RESIZE_SVEC(in_ar, c_dsp_mult_27_w);
ai <= RESIZE_SVEC(in_ai, c_dsp_mult_27_w);
br <= RESIZE_SVEC(in_br, c_dsp_mult_27_w);
bi <= RESIZE_SVEC(in_bi, c_dsp_mult_27_w) WHEN g_conjugate_b=FALSE ELSE TO_SVEC(-TO_SINT(in_bi), c_dsp_mult_27_w);
u0 : ip_arria10_e2sg_complex_mult
u0 : ip_arria10_e2sg_complex_mult_27b
PORT MAP (
aclr => rst,
clock => clk,
dataa_imag => ai,
dataa_real => ar,
datab_imag => bi,
datab_real => br,
ena => clken,
result_imag => mult_im,
result_real => mult_re
);
aclr => rst,
clock => clk,
dataa_imag => ai,
dataa_real => ar,
datab_imag => bi,
datab_real => br,
ena => clken,
result_imag => mult_im,
result_real => mult_re
);
-- Back to true input widths and then resize for output width
result_re <= RESIZE_SVEC(mult_re, g_out_p_w);
result_im <= RESIZE_SVEC(mult_im, g_out_p_w);
END GENERATE;
-------------------------------------------------------------------------------
-- Model: forward concatenated inputs to the 'result' output
--
-- Example:
-- ______
-- Input B.real (in_br) = 0x1111 --> | |
-- .imag (in_bi) = 0xBBBB --> | |
-- | mult | --> Output result.real = 0x00000000
-- Input A.real (in_ar) = 0x0000 --> | | .imag = 0xBBBBAAAA
-- .imag (in_ai) = 0xAAAA --> |______|
--
-- Note: this model is synthsizable as well.
--
-------------------------------------------------------------------------------
gen_sim_level_1 : IF g_sim=TRUE AND g_sim_level=1 GENERATE --FIXME: g_sim required? This is synthesizable.
result_re_undelayed <= in_br & in_ar;
result_im_undelayed <= in_bi & in_ai;
u_common_pipeline_re : entity common_lib.common_pipeline
generic map (
g_pipeline => 3,
g_in_dat_w => g_in_b_w+g_in_a_w,
g_out_dat_w => g_out_p_w
-----------------------------------------------------------------------------
-- RTL variants that can infer multipliers for a technology, fits all widths
-----------------------------------------------------------------------------
gen_ip_stratixiv_rtl : IF g_variant="RTL" AND g_technology=c_tech_stratixiv GENERATE
u0 : ip_stratixiv_complex_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_conjugate_b => g_conjugate_b,
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 (
clk => clk,
in_dat => result_re_undelayed,
out_dat => result_re
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;
u_common_pipeline_im : entity common_lib.common_pipeline
generic map (
g_pipeline => 3,
g_in_dat_w => g_in_b_w+g_in_a_w,
g_out_dat_w => g_out_p_w
-- RTL variant is the same for unb2, unb2a and unb2b
gen_ip_arria10_rtl : IF g_variant="RTL" AND (g_technology=c_tech_arria10 OR
g_technology=c_tech_arria10_e3sge3 OR
g_technology=c_tech_arria10_e1sg OR
g_technology=c_tech_arria10_e2sg) GENERATE
u0 : ip_arria10_complex_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_conjugate_b => g_conjugate_b,
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 (
clk => clk,
in_dat => result_im_undelayed,
out_dat => result_im
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;
-- RTL variant is the same for unb2, unb2a and unb2b
gen_ip_arria10_rtl_canonical : IF g_variant="RTL_C" AND (g_technology=c_tech_arria10 OR
g_technology=c_tech_arria10_e3sge3 OR
g_technology=c_tech_arria10_e1sg OR
g_technology=c_tech_arria10_e2sg) GENERATE
-- support g_conjugate_b
bi <= in_bi WHEN g_conjugate_b=FALSE ELSE TO_SVEC(-TO_SINT(in_bi), g_in_b_w);
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_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 => bi,
result_re => result_re,
result_im => result_im
);
END GENERATE;
end str;
......
......@@ -361,6 +361,19 @@ PACKAGE tech_mult_component_pkg IS
);
END COMPONENT;
COMPONENT ip_arria10_e1sg_complex_mult_27b is
PORT (
dataa_real : in std_logic_vector(26 downto 0) := (others => '0'); -- complex_input.dataa_real
dataa_imag : in std_logic_vector(26 downto 0) := (others => '0'); -- .dataa_imag
datab_real : in std_logic_vector(26 downto 0) := (others => '0'); -- .datab_real
datab_imag : in std_logic_vector(26 downto 0) := (others => '0'); -- .datab_imag
clock : in std_logic := '0'; -- .clk
aclr : in std_logic := '0'; -- .aclr
ena : in std_logic := '0'; -- .ena
result_real : out std_logic_vector(53 downto 0); -- complex_output.result_real
result_imag : out std_logic_vector(53 downto 0) -- .result_imag
);
END COMPONENT;
-----------------------------------------------------------------------------
-- Arria 10 e2sg components
-----------------------------------------------------------------------------
......@@ -426,4 +439,17 @@ PACKAGE tech_mult_component_pkg IS
);
END COMPONENT;
COMPONENT ip_arria10_e2sg_complex_mult_27b is
PORT (
dataa_real : in std_logic_vector(26 downto 0) := (others => '0'); -- complex_input.dataa_real
dataa_imag : in std_logic_vector(26 downto 0) := (others => '0'); -- .dataa_imag
datab_real : in std_logic_vector(26 downto 0) := (others => '0'); -- .datab_real
datab_imag : in std_logic_vector(26 downto 0) := (others => '0'); -- .datab_imag
clock : in std_logic := '0'; -- .clk
aclr : in std_logic := '0'; -- .aclr
ena : in std_logic := '0'; -- .ena
result_real : out std_logic_vector(53 downto 0); -- complex_output.result_real
result_imag : out std_logic_vector(53 downto 0) -- .result_imag
);
END COMPONENT;
END tech_mult_component_pkg;
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