diff --git a/libraries/technology/ip_arria10/complex_mult/README.txt b/libraries/technology/ip_arria10/complex_mult/README.txt new file mode 100644 index 0000000000000000000000000000000000000000..6884ec9c599bf7d01ffed812c8a3a2a9bbb09398 --- /dev/null +++ b/libraries/technology/ip_arria10/complex_mult/README.txt @@ -0,0 +1,55 @@ +README.txt for $RADIOHDL/libraries/technology/ip_arria10/complex_mult + +1) Porting +2) IP component +3) Compilation, simulation and verification +4) Synthesis +5) Remarks + + +1) Porting + +The complex_mult IP was ported manually from Quartus v11.1 for Stratix IV to Quartus 15.0 for Arria10 by creating it in Qsys using +the same parameter settings. + + +2) IP component + +The generated IP is not kept in SVN, only the Qsys source file: + + ip_arria10_complex_mult.qsys + +Therefore first the IP needs to be generated using: + + ./generate_ip.sh + + +3) Compilation, simulation and verification + +The generated IP also contains a msim_setup.tcl file that was used to manually create: + + compile_ip.tcl + +This compile_ip.tcl is in the hdllib.cfg and gets compiled before the other code. + + +4) Synthesis + +No synthesis trials were done, because this will implicitely be done when the IP is used in a design. The QIP file: + + generated/ip_arria10_complex_mult.qip + +is included in the hdllib.cfg and contains what is needed to synthesize the IP. + + +5) Remarks + +a) Use generated IP specific library clause name + + The generated ip_arria10_<lib_name>.vhd uses an IP specific library name. Therefore the hdllib.cfg uses the IP + specific library as library clause name to make it known: + + hdl_lib_name = ip_arria10_<lib_name> + hdl_library_clause_name = ip_arria10_<lib_name>_<ip_specific> + + \ No newline at end of file diff --git a/libraries/technology/ip_arria10/complex_mult/compile_ip.tcl b/libraries/technology/ip_arria10/complex_mult/compile_ip.tcl new file mode 100644 index 0000000000000000000000000000000000000000..3605025500e6c982ffd70b0fa128c6ad8f6bef76 --- /dev/null +++ b/libraries/technology/ip_arria10/complex_mult/compile_ip.tcl @@ -0,0 +1,35 @@ +#------------------------------------------------------------------------------ +# +# Copyright (C) 2015 +# ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/> +# JIVE (Joint Institute for VLBI in Europe) <http://www.jive.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/>. +# +#------------------------------------------------------------------------------ + +# This file is based on generated file generated/sim/mentor/msim_setup.tcl +# - the values for modelsim_search_libraries key in the hdllib.cfg follow from altera libraries vmap section in the msim_setup.tcl +# - vmap for the IP specific libraries and compile all IP source files into those libraries similar as in the msim_setup.tcl +# - replace QSYS_SIMDIR by IP_DIR + +set IP_DIR "$env(RADIOHDL)/libraries/technology/ip_arria10/complex_mult/generated/sim" + +#vlib ./work/ ;# Assume library work already exists + +vmap ip_arria10_complex_mult_altmult_complex_150 ./work/ + + vlog "$IP_DIR/../altmult_complex_150/sim/ip_arria10_complex_mult_altmult_complex_150_35pzchy.v" -work ip_arria10_complex_mult_altmult_complex_150 + vcom "$IP_DIR/ip_arria10_complex_mult.vhd" diff --git a/libraries/technology/ip_arria10/complex_mult/generate_ip.sh b/libraries/technology/ip_arria10/complex_mult/generate_ip.sh new file mode 100755 index 0000000000000000000000000000000000000000..32f0f2c0987bdb4e93d39198bb6e34564e13cf27 --- /dev/null +++ b/libraries/technology/ip_arria10/complex_mult/generate_ip.sh @@ -0,0 +1,44 @@ +#!/bin/bash +# -------------------------------------------------------------------------- # +# +# Copyright (C) 2014 +# ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/> +# JIVE (Joint Institute for VLBI in Europe) <http://www.jive.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/>. +# +# -------------------------------------------------------------------------- # +# +# Purpose: Generate IP with Qsys +# Description: +# Generate the IP in a separate generated/ subdirectory. +# +# Usage: +# +# ./generate_ip.sh +# + +# Tool settings for selected target "unb2" with arria10 +. ${RADIOHDL}/tools/quartus/set_quartus unb2 + +#qsys-generate --help + +# Only generate the source IP +# - use --synthesis=VHDL to have top level in VHDL similar as with MegaWizard +qsys-generate ip_arria10_complex_mult.qsys \ + --synthesis=VHDL \ + --simulation=VHDL \ + --output-directory=generated \ + --allow-mixed-language-simulation diff --git a/libraries/technology/ip_arria10/complex_mult/hdllib.cfg b/libraries/technology/ip_arria10/complex_mult/hdllib.cfg new file mode 100644 index 0000000000000000000000000000000000000000..d6aaa13158b29a774e47bf257b8efffcc7e8d5a3 --- /dev/null +++ b/libraries/technology/ip_arria10/complex_mult/hdllib.cfg @@ -0,0 +1,16 @@ +hdl_lib_name = ip_arria10_complex_mult +hdl_library_clause_name = ip_arria10_complex_mult_altmult_complex_150 +hdl_lib_uses_synth = +hdl_lib_uses_sim = + +hdl_lib_technology = ip_arria10 + +modelsim_compile_ip_files = + $RADIOHDL/libraries/technology/ip_arria10/complex_mult/compile_ip.tcl + +synth_files = + +test_bench_files = + +quartus_qip_files = + generated/ip_arria10_complex_mult.qip diff --git a/libraries/technology/ip_arria10/complex_mult/ip_arria10_complex_mult.qsys b/libraries/technology/ip_arria10/complex_mult/ip_arria10_complex_mult.qsys new file mode 100644 index 0000000000000000000000000000000000000000..7d4a9cec11f2fee08a1d9f2d86792fb138d7cf6e --- /dev/null +++ b/libraries/technology/ip_arria10/complex_mult/ip_arria10_complex_mult.qsys @@ -0,0 +1,88 @@ +<?xml version="1.0" encoding="UTF-8"?> +<system name="$${FILENAME}"> + <component + name="$${FILENAME}" + displayName="$${FILENAME}" + version="1.0" + description="" + tags="INTERNAL_COMPONENT=true" + categories="" /> + <parameter name="bonusData"><![CDATA[bonusData +{ + element $${FILENAME} + { + } + element altmult_complex_0 + { + datum _sortIndex + { + value = "0"; + type = "int"; + } + } +} +]]></parameter> + <parameter name="clockCrossingAdapter" value="HANDSHAKE" /> + <parameter name="device" value="10AS066H2F34E1SG" /> + <parameter name="deviceFamily" value="Arria 10" /> + <parameter name="deviceSpeedGrade" value="1" /> + <parameter name="fabricMode" value="QSYS" /> + <parameter name="generateLegacySim" value="false" /> + <parameter name="generationId" value="0" /> + <parameter name="globalResetBus" value="false" /> + <parameter name="hdlLanguage" value="VERILOG" /> + <parameter name="hideFromIPCatalog" value="true" /> + <parameter name="lockedInterfaceDefinition" value="" /> + <parameter name="maxAdditionalLatency" value="1" /> + <parameter name="projectName" value="" /> + <parameter name="sopcBorderPoints" value="false" /> + <parameter name="systemHash" value="0" /> + <parameter name="testBenchDutName" value="" /> + <parameter name="timeStamp" value="0" /> + <parameter name="useTestBenchNamingPattern" value="false" /> + <instanceScript></instanceScript> + <interface + name="complex_input" + internal="altmult_complex_0.complex_input" + type="conduit" + dir="end"> + <port name="dataa_real" internal="dataa_real" /> + <port name="dataa_imag" internal="dataa_imag" /> + <port name="datab_real" internal="datab_real" /> + <port name="datab_imag" internal="datab_imag" /> + <port name="clock" internal="clock" /> + <port name="aclr" internal="aclr" /> + <port name="ena" internal="ena" /> + </interface> + <interface + name="complex_output" + internal="altmult_complex_0.complex_output" + type="conduit" + dir="end"> + <port name="result_real" internal="result_real" /> + <port name="result_imag" internal="result_imag" /> + </interface> + <module + name="altmult_complex_0" + kind="altmult_complex" + version="15.0" + enabled="1" + autoexport="1"> + <parameter name="CBX_AUTO_BLACKBOX" value="ALL" /> + <parameter name="DEVICE_FAMILY" value="Arria 10" /> + <parameter name="GUI_DYNAMIC_COMPLEX" value="false" /> + <parameter name="GUI_USE_ACLR" value="true" /> + <parameter name="GUI_USE_CLKEN" value="true" /> + <parameter name="IMPLEMENTATION_STYLE" value="AUTO" /> + <parameter name="PIPELINE" value="3" /> + <parameter name="REPRESENTATION_A" value="1" /> + <parameter name="REPRESENTATION_B" value="1" /> + <parameter name="WIDTH_A" value="18" /> + <parameter name="WIDTH_B" value="18" /> + <parameter name="WIDTH_RESULT" value="36" /> + </module> + <interconnectRequirement for="$system" name="qsys_mm.clockCrossingAdapter" value="HANDSHAKE" /> + <interconnectRequirement for="$system" name="qsys_mm.enableEccProtection" value="FALSE" /> + <interconnectRequirement for="$system" name="qsys_mm.insertDefaultSlave" value="FALSE" /> + <interconnectRequirement for="$system" name="qsys_mm.maxAdditionalLatency" value="1" /> +</system> diff --git a/libraries/technology/ip_arria10/complex_mult_rtl/hdllib.cfg b/libraries/technology/ip_arria10/complex_mult_rtl/hdllib.cfg new file mode 100644 index 0000000000000000000000000000000000000000..e001e9caee5365c4b340ed56e617043bae7005f8 --- /dev/null +++ b/libraries/technology/ip_arria10/complex_mult_rtl/hdllib.cfg @@ -0,0 +1,11 @@ +hdl_lib_name = ip_arria10_complex_mult_rtl +hdl_library_clause_name = ip_arria10_complex_mult_rtl_lib +hdl_lib_uses_synth = +hdl_lib_uses_sim = + +hdl_lib_technology = ip_arria10 + +synth_files = + ip_arria10_complex_mult_rtl.vhd + +test_bench_files = diff --git a/libraries/technology/ip_arria10/complex_mult_rtl/ip_arria10_complex_mult_rtl.vhd b/libraries/technology/ip_arria10/complex_mult_rtl/ip_arria10_complex_mult_rtl.vhd new file mode 100644 index 0000000000000000000000000000000000000000..5d480da7a8781275957ba261ac3468669cb15264 --- /dev/null +++ b/libraries/technology/ip_arria10/complex_mult_rtl/ip_arria10_complex_mult_rtl.vhd @@ -0,0 +1,260 @@ +------------------------------------------------------------------------------- +-- +-- Copyright (C) 2009 +-- 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/>. +-- +------------------------------------------------------------------------------- + +LIBRARY IEEE; +USE IEEE.std_logic_1164.ALL; +USE IEEE.numeric_std.ALL; + +-- +-- Function: Signed complex multiply +-- p = a * b when g_conjugate_b = FALSE +-- = (ar + j ai) * (br + j bi) +-- = ar*br - ai*bi + j ( ar*bi + ai*br) +-- +-- p = a * conj(b) when g_conjugate_b = TRUE +-- = (ar + j ai) * (br - j bi) +-- = ar*br + ai*bi + j (-ar*bi + ai*br) +-- +-- Architectures: +-- . rtl : uses RTL to have all registers in one clocked process +-- + +ENTITY ip_arria10_complex_mult_rtl 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; + +ARCHITECTURE str OF ip_arria10_complex_mult_rtl 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; + + CONSTANT c_prod_w : NATURAL := g_in_a_w+g_in_b_w; + CONSTANT c_sum_w : NATURAL := c_prod_w+1; + +-- CONSTANT c_re_add_sub : STRING := sel_a_b(g_conjugate_b, "ADD", "SUB"); +-- CONSTANT c_im_add_sub : STRING := sel_a_b(g_conjugate_b, "SUB", "ADD"); + + -- registers + 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 reg_prod_ar_br : SIGNED(c_prod_w-1 DOWNTO 0); -- re + SIGNAL reg_prod_ai_bi : SIGNED(c_prod_w-1 DOWNTO 0); + SIGNAL reg_prod_ai_br : SIGNED(c_prod_w-1 DOWNTO 0); -- im + SIGNAL reg_prod_ar_bi : SIGNED(c_prod_w-1 DOWNTO 0); + SIGNAL reg_sum_re : SIGNED(c_sum_w-1 DOWNTO 0); + SIGNAL reg_sum_im : SIGNED(c_sum_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); + + -- combinatorial + 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 nxt_prod_ar_br : SIGNED(c_prod_w-1 DOWNTO 0); -- re + SIGNAL nxt_prod_ai_bi : SIGNED(c_prod_w-1 DOWNTO 0); + SIGNAL nxt_prod_ai_br : SIGNED(c_prod_w-1 DOWNTO 0); -- im + SIGNAL nxt_prod_ar_bi : SIGNED(c_prod_w-1 DOWNTO 0); + SIGNAL nxt_sum_re : SIGNED(c_sum_w-1 DOWNTO 0); + SIGNAL nxt_sum_im : SIGNED(c_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); + + -- the active 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 prod_ar_br : SIGNED(c_prod_w-1 DOWNTO 0); -- re + SIGNAL prod_ai_bi : SIGNED(c_prod_w-1 DOWNTO 0); + SIGNAL prod_ai_br : SIGNED(c_prod_w-1 DOWNTO 0); -- im + SIGNAL prod_ar_bi : SIGNED(c_prod_w-1 DOWNTO 0); + SIGNAL sum_re : SIGNED(c_sum_w-1 DOWNTO 0); + SIGNAL sum_im : SIGNED(c_sum_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_prod_ar_br <= (OTHERS=>'0'); + reg_prod_ai_bi <= (OTHERS=>'0'); + reg_prod_ai_br <= (OTHERS=>'0'); + reg_prod_ar_bi <= (OTHERS=>'0'); + reg_sum_re <= (OTHERS=>'0'); + reg_sum_im <= (OTHERS=>'0'); + reg_result_re <= (OTHERS=>'0'); + reg_result_im <= (OTHERS=>'0'); + ELSIF clken='1' THEN + reg_ar <= nxt_ar; -- inputs + reg_ai <= nxt_ai; + reg_br <= nxt_br; + reg_bi <= nxt_bi; + reg_prod_ar_br <= nxt_prod_ar_br; -- products for re + reg_prod_ai_bi <= nxt_prod_ai_bi; + reg_prod_ai_br <= nxt_prod_ai_br; -- products for im + reg_prod_ar_bi <= nxt_prod_ar_bi; + reg_sum_re <= nxt_sum_re; -- sum + reg_sum_im <= nxt_sum_im; + reg_result_re <= nxt_result_re; -- result sum after optional register stage + reg_result_im <= nxt_result_im; + 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; + + + ------------------------------------------------------------------------------ + -- Products + ------------------------------------------------------------------------------ + + nxt_prod_ar_br <= ar * br; -- products for re + nxt_prod_ai_bi <= ai * bi; + nxt_prod_ai_br <= ai * br; -- products for im + nxt_prod_ar_bi <= ar * bi; + + no_product_reg : IF g_pipeline_product=0 GENERATE -- wired + prod_ar_br <= nxt_prod_ar_br; + prod_ai_bi <= nxt_prod_ai_bi; + prod_ai_br <= nxt_prod_ai_br; + prod_ar_bi <= nxt_prod_ar_bi; + END GENERATE; + gen_product_reg : IF g_pipeline_product>0 GENERATE -- register + prod_ar_br <= reg_prod_ar_br; + prod_ai_bi <= reg_prod_ai_bi; + prod_ai_br <= reg_prod_ai_br; + prod_ar_bi <= reg_prod_ar_bi; + END GENERATE; + + + ------------------------------------------------------------------------------ + -- Sum + ------------------------------------------------------------------------------ + + -- Re + -- . "ADD" for a*conj(b) : ar*br + ai*bi + -- . "SUB" for a*b : ar*br - ai*bi + gen_re_add : IF g_conjugate_b GENERATE + nxt_sum_re <= RESIZE_NUM(prod_ar_br, c_sum_w) + prod_ai_bi; + END GENERATE; + gen_re_sub : IF NOT g_conjugate_b GENERATE + nxt_sum_re <= RESIZE_NUM(prod_ar_br, c_sum_w) - prod_ai_bi; + END GENERATE; + + -- Im + -- . "ADD" for a*b : ai*br + ar*bi + -- . "SUB" for a*conj(b) : ai*br - ar*bi + gen_im_add : IF NOT g_conjugate_b GENERATE + nxt_sum_im <= RESIZE_NUM(prod_ai_br, c_sum_w) + prod_ar_bi; + END GENERATE; + gen_im_sub : IF g_conjugate_b GENERATE + nxt_sum_im <= RESIZE_NUM(prod_ai_br, c_sum_w) - prod_ar_bi; + END GENERATE; + + + no_adder_reg : IF g_pipeline_adder=0 GENERATE -- wired + sum_re <= nxt_sum_re; + sum_im <= nxt_sum_im; + END GENERATE; + gen_adder_reg : IF g_pipeline_adder>0 GENERATE -- register + sum_re <= reg_sum_re; + sum_im <= reg_sum_im; + 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;