OpenCores
URL https://opencores.org/ocsvn/astron_multiplier/astron_multiplier/trunk

Subversion Repositories astron_multiplier

[/] [astron_multiplier/] [trunk/] [ip_stratixiv_complex_mult_rtl.vhd] - Blame information for rev 3

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 danv
-------------------------------------------------------------------------------
2
--
3 3 danv
-- Copyright 2020
4 2 danv
-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
5
-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
6 3 danv
-- 
7
-- Licensed under the Apache License, Version 2.0 (the "License");
8
-- you may not use this file except in compliance with the License.
9
-- You may obtain a copy of the License at
10
-- 
11
--     http://www.apache.org/licenses/LICENSE-2.0
12
-- 
13
-- Unless required by applicable law or agreed to in writing, software
14
-- distributed under the License is distributed on an "AS IS" BASIS,
15
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
-- See the License for the specific language governing permissions and
17
-- limitations under the License.
18 2 danv
--
19
-------------------------------------------------------------------------------
20
 
21
LIBRARY IEEE;
22
USE IEEE.std_logic_1164.ALL;
23
USE IEEE.numeric_std.ALL;
24
 
25
--
26
-- Function: Signed complex multiply
27
--   p = a * b       when g_conjugate_b = FALSE
28
--     = (ar + j ai) * (br + j bi)
29
--     =  ar*br - ai*bi + j ( ar*bi + ai*br)
30
--
31
--   p = a * conj(b) when g_conjugate_b = TRUE
32
--     = (ar + j ai) * (br - j bi)
33
--     =  ar*br + ai*bi + j (-ar*bi + ai*br)
34
--
35
-- Architectures:
36
-- . rtl          : uses RTL to have all registers in one clocked process
37
-- . str          : uses two RTL instances of common_mult_add2 for out_pr and out_pi
38
-- . str_stratix4 : uses two Stratix4 instances of common_mult_add2 for out_pr and out_pi
39
-- . stratix4     : uses MegaWizard component from common_complex_mult(stratix4).vhd
40
-- . rtl_dsp      : uses RTL with one process (as in Altera example)
41
-- . altera_rtl   : uses RTL with one process (as in Altera example, by Raj R. Thilak)
42
--
43
-- Preferred architecture: 'str', see synth\quartus\common_top.vhd
44
 
45
ENTITY ip_stratixiv_complex_mult_rtl IS
46
  GENERIC (
47
    g_in_a_w           : POSITIVE;
48
    g_in_b_w           : POSITIVE;
49
    g_out_p_w          : POSITIVE;          -- default use g_out_p_w = g_in_a_w+g_in_b_w = c_prod_w
50
    g_conjugate_b      : BOOLEAN := FALSE;
51
    g_pipeline_input   : NATURAL := 1;      -- 0 or 1
52
    g_pipeline_product : NATURAL := 0;      -- 0 or 1
53
    g_pipeline_adder   : NATURAL := 1;      -- 0 or 1
54
    g_pipeline_output  : NATURAL := 1       -- >= 0
55
  );
56
  PORT (
57
    rst        : IN   STD_LOGIC := '0';
58
    clk        : IN   STD_LOGIC;
59
    clken      : IN   STD_LOGIC := '1';
60
    in_ar      : IN   STD_LOGIC_VECTOR(g_in_a_w-1 DOWNTO 0);
61
    in_ai      : IN   STD_LOGIC_VECTOR(g_in_a_w-1 DOWNTO 0);
62
    in_br      : IN   STD_LOGIC_VECTOR(g_in_b_w-1 DOWNTO 0);
63
    in_bi      : IN   STD_LOGIC_VECTOR(g_in_b_w-1 DOWNTO 0);
64
    result_re  : OUT  STD_LOGIC_VECTOR(g_out_p_w-1 DOWNTO 0);
65
    result_im  : OUT  STD_LOGIC_VECTOR(g_out_p_w-1 DOWNTO 0)
66
  );
67
END ip_stratixiv_complex_mult_rtl;
68
 
69
ARCHITECTURE str OF ip_stratixiv_complex_mult_rtl IS
70
 
71
  FUNCTION RESIZE_NUM(s : SIGNED; w : NATURAL) RETURN SIGNED IS
72
  BEGIN
73
    -- extend sign bit or keep LS part
74
    IF w>s'LENGTH THEN
75
      RETURN RESIZE(s, w);                    -- extend sign bit
76
    ELSE
77
      RETURN SIGNED(RESIZE(UNSIGNED(s), w));  -- keep LSbits (= vec[w-1:0])
78
    END IF;
79
  END;
80
 
81
  CONSTANT c_prod_w     : NATURAL := g_in_a_w+g_in_b_w;
82
  CONSTANT c_sum_w      : NATURAL := c_prod_w+1;
83
 
84
--  CONSTANT c_re_add_sub : STRING := sel_a_b(g_conjugate_b, "ADD", "SUB");
85
--  CONSTANT c_im_add_sub : STRING := sel_a_b(g_conjugate_b, "SUB", "ADD");
86
 
87
  -- registers
88
  SIGNAL reg_ar         : SIGNED(g_in_a_w-1 DOWNTO 0);
89
  SIGNAL reg_ai         : SIGNED(g_in_a_w-1 DOWNTO 0);
90
  SIGNAL reg_br         : SIGNED(g_in_b_w-1 DOWNTO 0);
91
  SIGNAL reg_bi         : SIGNED(g_in_b_w-1 DOWNTO 0);
92
  SIGNAL reg_prod_ar_br : SIGNED(c_prod_w-1 DOWNTO 0);  -- re
93
  SIGNAL reg_prod_ai_bi : SIGNED(c_prod_w-1 DOWNTO 0);
94
  SIGNAL reg_prod_ai_br : SIGNED(c_prod_w-1 DOWNTO 0);  -- im
95
  SIGNAL reg_prod_ar_bi : SIGNED(c_prod_w-1 DOWNTO 0);
96
  SIGNAL reg_sum_re     : SIGNED(c_sum_w-1 DOWNTO 0);
97
  SIGNAL reg_sum_im     : SIGNED(c_sum_w-1 DOWNTO 0);
98
  SIGNAL reg_result_re  : SIGNED(g_out_p_w-1 DOWNTO 0);
99
  SIGNAL reg_result_im  : SIGNED(g_out_p_w-1 DOWNTO 0);
100
 
101
  -- combinatorial
102
  SIGNAL nxt_ar         : SIGNED(g_in_a_w-1 DOWNTO 0);
103
  SIGNAL nxt_ai         : SIGNED(g_in_a_w-1 DOWNTO 0);
104
  SIGNAL nxt_br         : SIGNED(g_in_b_w-1 DOWNTO 0);
105
  SIGNAL nxt_bi         : SIGNED(g_in_b_w-1 DOWNTO 0);
106
  SIGNAL nxt_prod_ar_br : SIGNED(c_prod_w-1 DOWNTO 0);  -- re
107
  SIGNAL nxt_prod_ai_bi : SIGNED(c_prod_w-1 DOWNTO 0);
108
  SIGNAL nxt_prod_ai_br : SIGNED(c_prod_w-1 DOWNTO 0);  -- im
109
  SIGNAL nxt_prod_ar_bi : SIGNED(c_prod_w-1 DOWNTO 0);
110
  SIGNAL nxt_sum_re     : SIGNED(c_sum_w-1 DOWNTO 0);
111
  SIGNAL nxt_sum_im     : SIGNED(c_sum_w-1 DOWNTO 0);
112
  SIGNAL nxt_result_re  : SIGNED(g_out_p_w-1 DOWNTO 0);
113
  SIGNAL nxt_result_im  : SIGNED(g_out_p_w-1 DOWNTO 0);
114
 
115
  -- the active signals
116
  SIGNAL ar             : SIGNED(g_in_a_w-1 DOWNTO 0);
117
  SIGNAL ai             : SIGNED(g_in_a_w-1 DOWNTO 0);
118
  SIGNAL br             : SIGNED(g_in_b_w-1 DOWNTO 0);
119
  SIGNAL bi             : SIGNED(g_in_b_w-1 DOWNTO 0);
120
  SIGNAL prod_ar_br     : SIGNED(c_prod_w-1 DOWNTO 0);  -- re
121
  SIGNAL prod_ai_bi     : SIGNED(c_prod_w-1 DOWNTO 0);
122
  SIGNAL prod_ai_br     : SIGNED(c_prod_w-1 DOWNTO 0);  -- im
123
  SIGNAL prod_ar_bi     : SIGNED(c_prod_w-1 DOWNTO 0);
124
  SIGNAL sum_re         : SIGNED(c_sum_w-1 DOWNTO 0);
125
  SIGNAL sum_im         : SIGNED(c_sum_w-1 DOWNTO 0);
126
 
127
BEGIN
128
 
129
  ------------------------------------------------------------------------------
130
  -- Registers
131
  ------------------------------------------------------------------------------
132
 
133
  -- Put all potential registers in a single process for optimal DSP inferrence
134
  -- Use rst only if it is supported by the DSP primitive, else leave it at '0'
135
  p_reg : PROCESS (rst, clk)
136
  BEGIN
137
    IF rising_edge(clk) THEN
138
      IF rst='1' THEN
139
        reg_ar         <= (OTHERS=>'0');
140
        reg_ai         <= (OTHERS=>'0');
141
        reg_br         <= (OTHERS=>'0');
142
        reg_bi         <= (OTHERS=>'0');
143
        reg_prod_ar_br <= (OTHERS=>'0');
144
        reg_prod_ai_bi <= (OTHERS=>'0');
145
        reg_prod_ai_br <= (OTHERS=>'0');
146
        reg_prod_ar_bi <= (OTHERS=>'0');
147
        reg_sum_re     <= (OTHERS=>'0');
148
        reg_sum_im     <= (OTHERS=>'0');
149
        reg_result_re  <= (OTHERS=>'0');
150
        reg_result_im  <= (OTHERS=>'0');
151
      ELSIF clken='1' THEN
152
        reg_ar         <= nxt_ar;          -- inputs
153
        reg_ai         <= nxt_ai;
154
        reg_br         <= nxt_br;
155
        reg_bi         <= nxt_bi;
156
        reg_prod_ar_br <= nxt_prod_ar_br;  -- products for re
157
        reg_prod_ai_bi <= nxt_prod_ai_bi;
158
        reg_prod_ai_br <= nxt_prod_ai_br;  -- products for im
159
        reg_prod_ar_bi <= nxt_prod_ar_bi;
160
        reg_sum_re     <= nxt_sum_re;      -- sum
161
        reg_sum_im     <= nxt_sum_im;
162
        reg_result_re  <= nxt_result_re;   -- result sum after optional register stage
163
        reg_result_im  <= nxt_result_im;
164
      END IF;
165
    END IF;
166
  END PROCESS;
167
 
168
  ------------------------------------------------------------------------------
169
  -- Inputs
170
  ------------------------------------------------------------------------------
171
 
172
  nxt_ar <= SIGNED(in_ar);
173
  nxt_ai <= SIGNED(in_ai);
174
  nxt_br <= SIGNED(in_br);
175
  nxt_bi <= SIGNED(in_bi);
176
 
177
  no_input_reg : IF g_pipeline_input=0 GENERATE   -- wired
178
    ar <= nxt_ar;
179
    ai <= nxt_ai;
180
    br <= nxt_br;
181
    bi <= nxt_bi;
182
  END GENERATE;
183
 
184
  gen_input_reg : IF g_pipeline_input>0 GENERATE  -- register input
185
    ar <= reg_ar;
186
    ai <= reg_ai;
187
    br <= reg_br;
188
    bi <= reg_bi;
189
  END GENERATE;
190
 
191
 
192
  ------------------------------------------------------------------------------
193
  -- Products
194
  ------------------------------------------------------------------------------
195
 
196
  nxt_prod_ar_br <= ar * br;  -- products for re
197
  nxt_prod_ai_bi <= ai * bi;
198
  nxt_prod_ai_br <= ai * br;  -- products for im
199
  nxt_prod_ar_bi <= ar * bi;
200
 
201
  no_product_reg : IF g_pipeline_product=0 GENERATE   -- wired
202
    prod_ar_br <= nxt_prod_ar_br;
203
    prod_ai_bi <= nxt_prod_ai_bi;
204
    prod_ai_br <= nxt_prod_ai_br;
205
    prod_ar_bi <= nxt_prod_ar_bi;
206
  END GENERATE;
207
  gen_product_reg : IF g_pipeline_product>0 GENERATE  -- register
208
    prod_ar_br <= reg_prod_ar_br;
209
    prod_ai_bi <= reg_prod_ai_bi;
210
    prod_ai_br <= reg_prod_ai_br;
211
    prod_ar_bi <= reg_prod_ar_bi;
212
  END GENERATE;
213
 
214
 
215
  ------------------------------------------------------------------------------
216
  -- Sum
217
  ------------------------------------------------------------------------------
218
 
219
  -- Re
220
  -- . "ADD" for a*conj(b) : ar*br + ai*bi
221
  -- . "SUB" for a*b       : ar*br - ai*bi
222
  gen_re_add : IF g_conjugate_b GENERATE
223
    nxt_sum_re <= RESIZE_NUM(prod_ar_br, c_sum_w) + prod_ai_bi;
224
  END GENERATE;
225
  gen_re_sub : IF NOT g_conjugate_b GENERATE
226
    nxt_sum_re <= RESIZE_NUM(prod_ar_br, c_sum_w) - prod_ai_bi;
227
  END GENERATE;
228
 
229
  -- Im
230
  -- . "ADD" for a*b       : ai*br + ar*bi
231
  -- . "SUB" for a*conj(b) : ai*br - ar*bi
232
  gen_im_add : IF NOT g_conjugate_b GENERATE
233
    nxt_sum_im <= RESIZE_NUM(prod_ai_br, c_sum_w) + prod_ar_bi;
234
  END GENERATE;
235
  gen_im_sub : IF g_conjugate_b GENERATE
236
    nxt_sum_im <= RESIZE_NUM(prod_ai_br, c_sum_w) - prod_ar_bi;
237
  END GENERATE;
238
 
239
 
240
  no_adder_reg : IF g_pipeline_adder=0 GENERATE   -- wired
241
    sum_re <= nxt_sum_re;
242
    sum_im <= nxt_sum_im;
243
  END GENERATE;
244
  gen_adder_reg : IF g_pipeline_adder>0 GENERATE  -- register
245
    sum_re <= reg_sum_re;
246
    sum_im <= reg_sum_im;
247
  END GENERATE;
248
 
249
  ------------------------------------------------------------------------------
250
  -- Result sum after optional rounding
251
  ------------------------------------------------------------------------------
252
 
253
  nxt_result_re <= RESIZE_NUM(sum_re, g_out_p_w);
254
  nxt_result_im <= RESIZE_NUM(sum_im, g_out_p_w);
255
 
256
  no_result_reg : IF g_pipeline_output=0 GENERATE   -- wired
257
    result_re <= STD_LOGIC_VECTOR(nxt_result_re);
258
    result_im <= STD_LOGIC_VECTOR(nxt_result_im);
259
  END GENERATE;
260
  gen_result_reg : IF g_pipeline_output>0 GENERATE  -- register
261
    result_re <= STD_LOGIC_VECTOR(reg_result_re);
262
    result_im <= STD_LOGIC_VECTOR(reg_result_im);
263
  END GENERATE;
264
 
265
END ARCHITECTURE;

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.