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

Subversion Repositories viirf

[/] [viirf/] [trunk/] [src/] [sos_cascaded_top.vhd] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 Muraer
--------------------------------------------------------------------------------------------------------------
2
-- MIT License
3
--  
4
-- Copyright (c) 2017 Mario Mauerer
5
--  
6
-- Permission is hereby granted, free of charge, to any person obtaining a copy
7
-- of this software and associated documentation files (the "Software"), to deal
8
-- in the Software without restriction, including without limitation the rights
9
-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
-- copies of the Software, and to permit persons to whom the Software is
11
-- furnished to do so, subject to the following conditions:
12
-- 
13
-- The above copyright notice and this permission notice shall be included in all
14
-- copies or substantial portions of the Software.
15
-- 
16
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
-- SOFTWARE.
23
--
24
--------------------------------------------------------------------------------------------------------------
25
-- VHDL Naming Convention:
26
-- http://dz.ee.ethz.ch/en/information/hdl-help/vhdl-naming-conventions.html
27
--------------------------------------------------------------------------------------------------------------
28
--
29
-- VIIRF - Versatile IIR Filter
30
-- sos_cascaded_top.vhd
31
--
32
-- This is the filter's top-level file.
33
-- It applies the input gain, connects the direct-form 1 SOS/biquads in series, and applies
34
-- the output gain, if enabled.
35
--
36
-- Note: DatxDO is only valid when StrbxSO = '1'! The data can change
37
-- inbetween. 
38
--
39
-- The filter coefficients are provided to this unit via a generic coefficient
40
-- interface comprising the following signals. The coefficient are then stored in a
41
-- RAM (no vendor-specific constructs used). 
42
--
43
-- SectAddrxDI:
44
--      Address of the SOS/biquad for which the coefficients are provided.
45
--      Range: 0-NUM_SEC. Maximum allowable NUM_SEC: 255.
46
--      If SectAddrxDI = NUM_SEC and CoeffAddrxDI = 6, the filter's final
47
--      output gain is addressed. 
48
-- CoeffAddrxDI:
49
--      Address of the selected SOS coefficient. Range: 0-6. Coefficient mapping:
50
--      0 ==> b0
51
--      1 ==> b1
52
--      2 ==> b2
53
--      3 ==> a1
54
--      4 ==> a2
55
--      5 ==> g
56
--      6 ==> FinalGain (Can only be written if SectAddrxDI=NUM_SEC)
57
-- CoeffDatxDI:
58
--      Coefficient data of the addressed coefficient
59
-- CoeffValidxSI:
60
--      If set to high, data and addresses are valid and the coefficient data
61
--      is stored in an internal RAM. 
62
-- 
63
-- Generics/Configuration:
64
--
65
-- NUM_SEC:
66
--      Number of cascaded biquad sections to include. Max value: 255
67
-- W_DAT_INPUT:
68
--      Width of (signed) input data vector
69
-- GAIN_INPUT:
70
--      Filter input gain. Must be a power of two (left-shifts). Usable for
71
--      bit-extension / precision increase. If not used: set to 1.
72
-- W_SECT_DAT:
73
--      Width of SOS data path / width of SOS inputs/outputs. 
74
-- W_COEF:
75
--      Overall coefficient width (bits)
76
-- W_FRAC:
77
--      Fraction length of the coefficients (bits). Together with W_COEF, this
78
--      defines the Q-Notation of the quantized coefficients.
79
--      E.g., for Q1.15, set W_COEF=16 and W_FRAC=15.
80
-- SOSGAIN_EN:
81
--      Bool, if set to true, the output-gain stage of the SOS is generated / included
82
-- FINALGAIN_EN:
83
--      Bool, if set to true, the final filter output-gain stage is generated /
84
--      included
85
-- W_DAT_OUTPUT:
86
--      Width of the (signed) output data vector. Data is saturated to this
87
--      vector width.
88
-- W_DAT_INTF:
89
--      Width of the (std_logic_vector) address and data vectors of the generic
90
--      coefficient data interface.
91
-- USE_PIPELINE_CORE:
92
--      Bool, if set to true, the pipelined SOS core is used (more resource
93
--      usage, but higher clock rate possible). If set to false, the reuse-core
94
--      is utilized, which uses a single multiplier and a state-machine to
95
--      control the data flow.
96
 
97
library IEEE;
98
use IEEE.STD_LOGIC_1164.all;
99
use IEEE.NUMERIC_STD.all;
100
use IEEE.math_real.all;
101
 
102
 
103
entity sos_cascaded_top is
104
  generic(
105
    NUM_SEC           : integer := 27;
106
    W_DAT_INPUT       : integer := 16;
107
    GAIN_INPUT        : integer := 4;
108
    W_SECT_DAT        : integer := 23;
109
    W_COEF            : integer := 18;
110
    W_FRAC            : integer := 16;
111
    SOSGAIN_EN        : boolean := false;
112
    FINALGAIN_EN      : boolean := true;
113
    W_DAT_OUTPUT      : integer := 32;
114
    W_DAT_INTF        : integer := 32;
115
    USE_PIPELINE_CORE : boolean := true
116
    );
117
  port (
118
    ClkxCI        : in  std_logic;      -- Clock input
119
    RstxRI        : in  std_logic;      -- Reset input, active high
120
    -- Filter Data:
121
    DatxDI        : in  signed(W_DAT_INPUT-1 downto 0);  -- Input data
122
    StrbxSI       : in  std_logic;      -- Input strobe
123
    -- Output data - Only valid with StrbxSO!
124
    DatxDO        : out signed(W_DAT_OUTPUT-1 downto 0);
125
    -- Output strobe - Indicates validity of DatxDO                                 
126
    StrbxSO       : out std_logic;
127
    -- Coefficient Configuration Interface: Description: See above
128
    SectAddrxDI   : in  std_logic_vector(W_DAT_INTF-1 downto 0);
129
    CoeffAddrxDI  : in  std_logic_vector(W_DAT_INTF-1 downto 0);
130
    CoeffDatxDI   : in  std_logic_vector(W_DAT_INTF-1 downto 0);
131
    CoeffValidxSI : in  std_logic
132
    );
133
end sos_cascaded_top;
134
 
135
architecture Behavioral of sos_cascaded_top is
136
 
137
-----------------------------------------------------------------------------
138
-- Components
139
-----------------------------------------------------------------------------
140
 
141
  -- This core is the pipelined core optimized for high clock rates.
142
  -- This comes at the cost of heavier multiplier usage. 
143
  component sos_core_df1 is
144
    generic (
145
      W_DAT      : integer;
146
      W_COEF     : integer;
147
      W_FRAC     : integer;
148
      SOSGAIN_EN : boolean);
149
    port (
150
      ClkxCI  : in  std_logic;
151
      RstxRI  : in  std_logic;
152
      DatxDI  : in  signed(W_DAT-1 downto 0);
153
      StrbxSI : in  std_logic;
154
      DatxDO  : out signed(W_DAT-1 downto 0);
155
      StrbxSO : out std_logic;
156
      b0xDI   : in  signed(W_COEF-1 downto 0);
157
      b1xDI   : in  signed(W_COEF-1 downto 0);
158
      b2xDI   : in  signed(W_COEF-1 downto 0);
159
      a1xDI   : in  signed(W_COEF-1 downto 0);
160
      a2xDI   : in  signed(W_COEF-1 downto 0);
161
      gxDI    : in  signed(W_COEF-1 downto 0));
162
  end component sos_core_df1;
163
 
164
 
165
  -- This core uses a state-machine arount a single multiplier.
166
  -- Due to this additional logic around the multiplier, its clock frequency is
167
  -- more limited than the fully pipelined implementation of the core. 
168
  component sos_core_df1_reuse is
169
    generic (
170
      W_DAT      : integer;
171
      W_COEF     : integer;
172
      W_FRAC     : integer;
173
      SOSGAIN_EN : boolean);
174
    port (
175
      ClkxCI  : in  std_logic;
176
      RstxRI  : in  std_logic;
177
      DatxDI  : in  signed(W_DAT-1 downto 0);
178
      StrbxSI : in  std_logic;
179
      DatxDO  : out signed(W_DAT-1 downto 0);
180
      StrbxSO : out std_logic;
181
      b0xDI   : in  signed(W_COEF-1 downto 0);
182
      b1xDI   : in  signed(W_COEF-1 downto 0);
183
      b2xDI   : in  signed(W_COEF-1 downto 0);
184
      a1xDI   : in  signed(W_COEF-1 downto 0);
185
      a2xDI   : in  signed(W_COEF-1 downto 0);
186
      gxDI    : in  signed(W_COEF-1 downto 0));
187
  end component sos_core_df1_reuse;
188
 
189
-----------------------------------------------------------------------------
190
-- Signal Declarations
191
-----------------------------------------------------------------------------
192
 
193
  -------------
194
  -- Constants:
195
  -------------
196
  -- Constants for the filter coefficient interface:
197
  -- Width of addresses for sections and coefficients of coefficient
198
  -- config interface. This is hardcoded.
199
  constant W_SECT_ADDR   : integer := 8;  -- Allows 255 sections
200
  constant W_COEFF_ADDR  : integer := 3;  -- A range from 0 - 6 is required
201
  -- Number of coefficients per section: 6 for SOS. (b0, b1, b2, a1, a2, g).
202
  -- This is fixed by the direct-form 1 implementation.
203
  constant NUM_COEF_SECT : integer := 6;
204
 
205
  -- Number of left-shifts required for filter input gain / bit extension.
206
  -- Note: GAIN_INPUT has to be a power of two, otherwise, the gain will not be
207
  -- what's expected...
208
  constant NUM_INPUT_LSHIFT  : integer                                       := integer(ceil(log2(real(GAIN_INPUT))));
209
  -- Vector to hold the expanded bits:
210
  constant INPUT_EXPAND_VECT : std_logic_vector(NUM_INPUT_LSHIFT-1 downto 0) := (others => '0');
211
 
212
  -- Values for output saturation. Two's complement min and max values, defined
213
  -- using bit-masks instead of integers, as W_DAT_OUTPUT can be > 32 bit.
214
  constant SAT_OUT_POS : signed(W_DAT_OUTPUT-1 downto 0) := (W_DAT_OUTPUT-1 => '0', others => '1');
215
  constant SAT_OUT_NEG : signed(W_DAT_OUTPUT-1 downto 0) := (W_DAT_OUTPUT-1 => '1', others => '0');
216
 
217
  -----------
218
  -- Signals:
219
  -----------
220
 
221
  -- Coefficient interface registers and signals:
222
  signal SectAddrxDN, SectAddrxDP     : std_logic_vector(W_DAT_INTF-1 downto 0) := (others => '0');
223
  signal CoeffAddrxDN, CoeffAddrxDP   : std_logic_vector(W_DAT_INTF-1 downto 0) := (others => '0');
224
  signal CoeffDatxDN, CoeffDatxDP     : std_logic_vector(W_DAT_INTF-1 downto 0) := (others => '0');
225
  signal CoeffValidxSN, CoeffValidxSP : std_logic                               := '0';
226
  signal SectAddrxS                   : unsigned(W_SECT_ADDR-1 downto 0)        := (others => '0');
227
  signal CoeffAddrxS                  : unsigned(W_COEFF_ADDR-1 downto 0)       := (others => '0');
228
 
229
  -- Coefficient registers/RAM: This stores the filter coefficients of each section.
230
  -- Each section has its own set of registers:
231
  type COEFREG_TYPE is array (NUM_COEF_SECT-1 downto 0) of signed(W_COEF-1 downto 0);
232
  type SECTREGS_TYPE is array (NUM_SEC-1 downto 0) of COEFREG_TYPE;
233
  -- RAM to store the 6 coefficients of each section.
234
  signal CoeffRamxDN, CoeffRamxDP   : SECTREGS_TYPE             := (others => (others => (others => '0')));
235
  -- Final output gain register. This exists only once per filter.
236
  signal FinalGainxDN, FinalGainxDP : signed(W_COEF-1 downto 0) := (others => '0');
237
 
238
  -- Connection wires between the series-connected second-order sections.
239
  -- One less than NUM_SEC required:
240
  type STRBWIRE_TYPE is array (NUM_SEC-2 downto 0) of std_logic;
241
  type DATWIRE_TYPE is array (NUM_SEC-2 downto 0) of signed(W_SECT_DAT-1 downto 0);
242
  signal StrbWiresxS : STRBWIRE_TYPE := (others => '0');
243
  signal DatWiresxS  : DATWIRE_TYPE  := (others => (others => '0'));
244
 
245
  -- Various registers/signals:
246
  signal RstxRN, RstxRP                 : std_logic                      := '0';
247
  signal InputDatxDN, InputDatxDP       : signed(W_DAT_INPUT-1 downto 0) := (others => '0');
248
  signal InputStrbxSN, InputStrbxSP     : std_logic                      := '0';
249
  -- Register for holding the left-shifted input signal. Bit-Expanded to
250
  -- W_SECT_DAT. This is input into the first SOS.
251
  signal InputDatLSxDN, InputDatLSxDP   : signed(W_SECT_DAT-1 downto 0)  := (others => '0');
252
  signal InputStrbLSxSN, InputStrbLSxSP : std_logic                      := '0';
253
  -- Outputs from the last SOS. We don't register this since there is directly
254
  -- a register at the output of the SOS-core.
255
  signal SOSDatxS                       : signed(W_SECT_DAT-1 downto 0)  := (others => '0');
256
  signal SOSStrbxS                      : std_logic                      := '0';
257
 
258
 
259
-----------------------------------------------------------------------------
260
begin  -- Behavioral
261
-----------------------------------------------------------------------------
262
 
263
-----------------------------------------------------------------------------
264
-- Wiring
265
-----------------------------------------------------------------------------
266
  -- Registering of the coefficient interface for route-timing relaxation
267
  CoeffAddrxDN  <= CoeffAddrxDI;
268
  SectAddrxDN   <= SectAddrxDI;
269
  CoeffDatxDN   <= CoeffDatxDI;
270
  CoeffValidxSN <= CoeffValidxSI;
271
 
272
  -- For internal use: Crop the address vectors to a shorter length.
273
  -- Potentially reduces routing delays.
274
  CoeffAddrxS <= unsigned(CoeffAddrxDP(W_COEFF_ADDR-1 downto 0));
275
  SectAddrxS  <= unsigned(SectAddrxDP(W_SECT_ADDR-1 downto 0));
276
 
277
  -- Local reset, for better timing if filter is (area-wise) large.
278
  -- This also resets the cascaded sections.
279
  RstxRN <= RstxRI;
280
 
281
  -- Data input register: For timing relaxation
282
  InputDatxDN  <= DatxDI;
283
  InputStrbxSN <= StrbxSI;
284
 
285
  -- Apply the Input-Gain and expand the bit-width for the following biquad sections:
286
  InputDatLSxDN  <= resize(signed(std_logic_vector(InputDatxDP) & INPUT_EXPAND_VECT), W_SECT_DAT);
287
  -- Also carry the strobe forward:
288
  InputStrbLSxSN <= InputStrbxSP;
289
 
290
-----------------------------------------------------------------------------
291
-- Processes
292
-----------------------------------------------------------------------------
293
 
294
  -- Reads the coefficients from the coefficient data interface
295
  -- and stores them to the coefficient RAM.
296
  CoeffWrite : process(CoeffAddrxS, CoeffDatxDP, CoeffRamxDP, CoeffValidxSP,
297
                       FinalGainxDP, SectAddrxS)
298
  begin
299
    -- Default Assignments:
300
    CoeffRamxDN  <= CoeffRamxDP;
301
    FinalGainxDN <= FinalGainxDP;
302
    -- Only write when valid = 1:
303
    if CoeffValidxSP = '1' then
304
      -- Write the regular section's coefficients:
305
      if SectAddrxS <= NUM_SEC-1 and CoeffAddrxS <= 5 then
306
        CoeffRamxDN(to_integer(SectAddrxS))(to_integer(CoeffAddrxS)) <= resize(signed(CoeffDatxDP), W_COEF);
307
      -- Write the final output gain of the filter:
308
      elsif SectAddrxS = NUM_SEC and CoeffAddrxS = 6 then
309
        FinalGainxDN <= resize(signed(CoeffDatxDP), W_COEF);
310
      end if;
311
    end if;
312
  end process CoeffWrite;
313
 
314
  -- Only create / generate the final output multiplier if it's actually enabled.
315
  -- This saves resources and latency.
316
  -- The signals defined in this block are not visible outside this
317
  -- generate-statement, hence there is a clocking-process here, too.
318
  -- The required latency for the strobe-signal is 4
319
  GenerateFinalMul : if FINALGAIN_EN = true generate
320
    constant W_MUL                              : integer                                       := W_COEF + W_SECT_DAT;
321
    constant W_RS                               : integer                                       := W_MUL - W_FRAC;
322
    signal gRegxDN, gRegxDP                     : signed(W_MUL-1 downto 0)                      := (others => '0');
323
    signal ShiftGainOutxDN, ShiftGainOutxDP     : signed(W_MUL-1 downto 0)                      := (others => '0');
324
    signal ShiftGainOutRSxDN, ShiftGainOutRSxDP : signed(W_RS-1 downto 0)                       := (others => '0');
325
    signal OutMulxDN, OutMulxDP                 : signed(W_DAT_OUTPUT-1 downto 0)               := (others => '0');
326
    -- Number of latency-cycles required for the strobe-output, if the final
327
    -- gain is used:
328
    constant NUM_CYC_DEL_STRB                   : integer                                       := 4;
329
    -- Strobe-shift register: The input strobe is shifted "through" this unit:
330
    signal StrbShiftxSN, StrbShiftxSP           : std_logic_vector(NUM_CYC_DEL_STRB-1 downto 0) := (others => '0');
331
  begin
332
 
333
    -- This process manages the section's output gain and saturation:
334
    FinalGain : process(FinalGainxDP, SOSDatxS, ShiftGainOutxDP, gRegxDP,
335
                        shiftGainOutRSxDP)
336
    begin
337
      -- Apply the final gain:
338
      gRegxDN           <= SOSDatxS * FinalGainxDP;
339
      -- Output divider: Get rid of the gain due to the integer algebra (2^W_FRAC):
340
      ShiftGainOutxDN   <= shift_right(gRegxDP, W_FRAC);
341
      -- Resize to a smaller vector for less routing delay for the upcoming saturation:
342
      ShiftGainOutRSxDN <= resize(ShiftGainOutxDP, W_RS);
343
 
344
      -- Output Saturation:
345
      if ShiftGainOutRSxDP > SAT_OUT_POS then
346
        OutMulxDN <= SAT_OUT_POS;
347
      elsif ShiftGainOutRSxDP < SAT_OUT_NEG then
348
        OutMulxDN <= SAT_OUT_NEG;
349
      else
350
        OutMulxDN <= resize(shiftGainOutRSxDP, W_DAT_OUTPUT);
351
      end if;
352
    end process FinalGain;
353
 
354
    -- The core's data output is the one where the final output gain has been applied to:
355
    DatxDO <= OutMulxDP;
356
 
357
    -- Delay the input strobe according to the latency of the core:
358
    StrobeShiftOutGain : process(SOSStrbxS,
359
                                 StrbShiftxSP(NUM_CYC_DEL_STRB-2 downto 0))
360
    begin
361
      StrbShiftxSN(0)                           <= SOSStrbxS;
362
      StrbShiftxSN(NUM_CYC_DEL_STRB-1 downto 1) <= StrbShiftxSP(NUM_CYC_DEL_STRB-2 downto 0);
363
    end process StrobeShiftOutGain;
364
 
365
    -- Strobe output:
366
    StrbxSO <= StrbShiftxSP(NUM_CYC_DEL_STRB-1);
367
 
368
    --The flip-flops needed if the output gain is used:
369
    FF_FinalMul : process (ClkxCI)
370
    begin
371
      if ClkxCI'event and ClkxCI = '1' then
372
        if RstxRI = '1' then
373
          gRegxDP           <= (others => '0');
374
          ShiftGainOutxDP   <= (others => '0');
375
          ShiftGainOutRSxDP <= (others => '0');
376
          OutMulxDP         <= (others => '0');
377
          StrbShiftxSP      <= (others => '0');
378
        else
379
          gRegxDP           <= gRegxDN;
380
          ShiftGainOutxDP   <= ShiftGainOutxDN;
381
          ShiftGainOutRSxDP <= ShiftGainOutRSxDN;
382
          OutMulxDP         <= OutMulxDN;
383
          StrbShiftxSP      <= StrbShiftxSn;
384
        end if;
385
      end if;
386
    end process FF_FinalMul;
387
 
388
  end generate;
389
 
390
 
391
  -- If the final filter output gain is not used: simply saturate the
392
  -- SOS-output to the output width of the filter.  
393
  -- The required latency for the strobe-signal is 1
394
  GenerateNoFinalMul : if FINALGAIN_EN = false generate
395
 
396
    signal OutSatxDN, OutSatxDP       : signed(W_DAT_OUTPUT-1 downto 0)               := (others => '0');
397
    -- Number of latency-cycles required for the strobe-output, if the final
398
    -- gain is used:
399
    constant NUM_CYC_DEL_STRB         : integer                                       := 1;
400
    -- Strobe-shift register: The input strobe is shifted "through" this unit:
401
    signal StrbShiftxSN, StrbShiftxSP : std_logic_vector(NUM_CYC_DEL_STRB-1 downto 0) := (others => '0');
402
  begin
403
 
404
    -- Saturation:
405
    OutSat : process(SOSDatxS)
406
    begin
407
      if SOSDatxS > SAT_OUT_POS then
408
        OutSatxDN <= SAT_OUT_POS;
409
      elsif SOSDatxS < SAT_OUT_NEG then
410
        OutSatxDN <= SAT_OUT_NEG;
411
      else
412
        OutSatxDN <= resize(SOSDatxS, W_DAT_OUTPUT);
413
      end if;
414
    end process OutSat;
415
 
416
    -- The core's data output is now saturated:
417
    DatxDO <= OutSatxDP;
418
 
419
    -- Delay the input strobe according to the latency of the core:
420
    StrobeShiftOutGain : process(SOSStrbxS,
421
                                 StrbShiftxSP(NUM_CYC_DEL_STRB-2 downto 0))
422
    begin
423
      StrbShiftxSN(0)                           <= SOSStrbxS;
424
      StrbShiftxSN(NUM_CYC_DEL_STRB-1 downto 1) <= StrbShiftxSP(NUM_CYC_DEL_STRB-2 downto 0);
425
    end process StrobeShiftOutGain;
426
 
427
    -- Strobe output:
428
    StrbxSO <= StrbShiftxSP(NUM_CYC_DEL_STRB-1);
429
 
430
    --The flip-flops needed if there is no final output gain:
431
    FF_NoFinalMul : process (ClkxCI)
432
    begin
433
      if ClkxCI'event and ClkxCI = '1' then
434
        if RstxRI = '1' then
435
          OutSatxDP    <= (others => '0');
436
          StrbShiftxSP <= (others => '0');
437
        else
438
          OutSatxDP    <= OutSatxDN;
439
          StrbShiftxSP <= StrbShiftxSN;
440
        end if;
441
      end if;
442
    end process FF_NoFinalMul;
443
 
444
  end generate;
445
 
446
 
447
  -- The local reset flip-flop:
448
  RstFF : process (ClkxCI)
449
  begin
450
    if ClkxCI'event and ClkxCI = '1' then
451
      RstxRP <= RstxRN;
452
    end if;
453
  end process RstFF;
454
 
455
 
456
  -- The flip-flops:
457
  FF : process (ClkxCI)
458
  begin
459
    if ClkxCI'event and ClkxCI = '1' then
460
      if RstxRP = '1' then
461
        SectAddrxDP    <= (others => '0');
462
        CoeffAddrxDP   <= (others => '0');
463
        CoeffDatxDP    <= (others => '0');
464
        CoeffValidxSP  <= '0';
465
        CoeffRamxDP    <= (others => (others => (others => '0')));
466
        FinalGainxDP   <= (others => '0');
467
        InputDatxDP    <= (others => '0');
468
        InputStrbxSP   <= '0';
469
        InputDatLSxDP  <= (others => '0');
470
        InputStrbLSxSP <= '0';
471
      else
472
        SectAddrxDP    <= SectAddrxDN;
473
        CoeffAddrxDP   <= CoeffAddrxDN;
474
        CoeffDatxDP    <= CoeffDatxDN;
475
        CoeffValidxSP  <= CoeffValidxSN;
476
        CoeffRamxDP    <= CoeffRamxDN;
477
        FinalGainxDP   <= FinalGainxDN;
478
        InputDatxDP    <= InputDatxDN;
479
        InputStrbxSP   <= InputStrbxSN;
480
        InputDatLSxDP  <= InputDatLSxDN;
481
        InputStrbLSxSP <= InputStrbLSxSN;
482
      end if;
483
    end if;
484
  end process FF;
485
 
486
 
487
-----------------------------------------------------------------------------
488
-- Instances
489
-----------------------------------------------------------------------------
490
 
491
  -- In the following, the SOS instances are cascaded.
492
  -- Both is done either for the pipelined or the reuse-core.
493
  -- Furthermore, if there is only one, two or more sections, the wiring is
494
  -- slightly different, as there are or are no middle or output sections.
495
 
496
  -- The pipelined cores are used:
497
  UsePipelineCore : if USE_PIPELINE_CORE = true generate
498
 
499
    -- Only a single SOS; Connect it directly to input/output
500
    SingleSec : if NUM_SEC = 1 generate
501
      SingleSOS : sos_core_df1
502
        generic map (
503
          W_DAT      => W_SECT_DAT,
504
          W_COEF     => W_COEF,
505
          W_FRAC     => W_FRAC,
506
          SOSGAIN_EN => SOSGAIN_EN)
507
        port map (
508
          ClkxCI  => ClkxCI,
509
          RstxRI  => RstxRP,
510
          DatxDI  => InputDatLSxDP,
511
          StrbxSI => InputStrbLSxSP,
512
          DatxDO  => SOSDatxS,
513
          StrbxSO => SOSStrbxS,
514
          b0xDI   => CoeffRamxDP(0)(0),
515
          b1xDI   => CoeffRamxDP(0)(1),
516
          b2xDI   => CoeffRamxDP(0)(2),
517
          a1xDI   => CoeffRamxDP(0)(3),
518
          a2xDI   => CoeffRamxDP(0)(4),
519
          gxDI    => CoeffRamxDP(0)(5));
520
    end generate SingleSec;
521
 
522
    -- Two cascaded SOS; Connected in series
523
    DualSec : if NUM_SEC = 2 generate
524
      InputSOS : sos_core_df1
525
        generic map (
526
          W_DAT      => W_SECT_DAT,
527
          W_COEF     => W_COEF,
528
          W_FRAC     => W_FRAC,
529
          SOSGAIN_EN => SOSGAIN_EN)
530
        port map (
531
          ClkxCI  => ClkxCI,
532
          RstxRI  => RstxRP,
533
          DatxDI  => InputDatLSxDP,
534
          StrbxSI => InputStrbLSxSP,
535
          DatxDO  => DatWiresxS(0),
536
          StrbxSO => StrbWiresxS(0),
537
          b0xDI   => CoeffRamxDP(0)(0),
538
          b1xDI   => CoeffRamxDP(0)(1),
539
          b2xDI   => CoeffRamxDP(0)(2),
540
          a1xDI   => CoeffRamxDP(0)(3),
541
          a2xDI   => CoeffRamxDP(0)(4),
542
          gxDI    => CoeffRamxDP(0)(5));
543
 
544
      OutSOS : sos_core_df1
545
        generic map (
546
          W_DAT      => W_SECT_DAT,
547
          W_COEF     => W_COEF,
548
          W_FRAC     => W_FRAC,
549
          SOSGAIN_EN => SOSGAIN_EN)
550
        port map (
551
          ClkxCI  => ClkxCI,
552
          RstxRI  => RstxRP,
553
          DatxDI  => DatWiresxS(0),
554
          StrbxSI => StrbWiresxS(0),
555
          DatxDO  => SOSDatxS,
556
          StrbxSO => SOSStrbxS,
557
          b0xDI   => CoeffRamxDP(1)(0),
558
          b1xDI   => CoeffRamxDP(1)(1),
559
          b2xDI   => CoeffRamxDP(1)(2),
560
          a1xDI   => CoeffRamxDP(1)(3),
561
          a2xDI   => CoeffRamxDP(1)(4),
562
          gxDI    => CoeffRamxDP(1)(5));
563
    end generate DualSec;
564
 
565
    -- More than 2 SOS sections; there is an input, middle and output section.
566
    -- Wired into a cascade
567
    MoreSec : if NUM_SEC > 2 generate
568
      CascadeSections : for I in 0 to NUM_SEC-1 generate
569
        InputSection : if I = 0 generate
570
          InputSOS : sos_core_df1
571
            generic map (
572
              W_DAT      => W_SECT_DAT,
573
              W_COEF     => W_COEF,
574
              W_FRAC     => W_FRAC,
575
              SOSGAIN_EN => SOSGAIN_EN)
576
            port map (
577
              ClkxCI  => ClkxCI,
578
              RstxRI  => RstxRP,
579
              DatxDI  => InputDatLSxDP,
580
              StrbxSI => InputStrbLSxSP,
581
              DatxDO  => DatWiresxS(I),
582
              StrbxSO => StrbWiresxS(I),
583
              b0xDI   => CoeffRamxDP(I)(0),
584
              b1xDI   => CoeffRamxDP(I)(1),
585
              b2xDI   => CoeffRamxDP(I)(2),
586
              a1xDI   => CoeffRamxDP(I)(3),
587
              a2xDI   => CoeffRamxDP(I)(4),
588
              gxDI    => CoeffRamxDP(I)(5));
589
        end generate InputSection;
590
 
591
        MiddleSections : if I > 0 and I < NUM_SEC-1 generate
592
          MidSOS : sos_core_df1
593
            generic map (
594
              W_DAT      => W_SECT_DAT,
595
              W_COEF     => W_COEF,
596
              W_FRAC     => W_FRAC,
597
              SOSGAIN_EN => SOSGAIN_EN)
598
            port map (
599
              ClkxCI  => ClkxCI,
600
              RstxRI  => RstxRP,
601
              DatxDI  => DatWiresxS(I-1),
602
              StrbxSI => StrbWiresxS(I-1),
603
              DatxDO  => DatWiresxS(I),
604
              StrbxSO => StrbWiresxS(I),
605
              b0xDI   => CoeffRamxDP(I)(0),
606
              b1xDI   => CoeffRamxDP(I)(1),
607
              b2xDI   => CoeffRamxDP(I)(2),
608
              a1xDI   => CoeffRamxDP(I)(3),
609
              a2xDI   => CoeffRamxDP(I)(4),
610
              gxDI    => CoeffRamxDP(I)(5));
611
        end generate MiddleSections;
612
 
613
        OutputSection : if I = NUM_SEC-1 generate
614
          OutSOS : sos_core_df1
615
            generic map (
616
              W_DAT      => W_SECT_DAT,
617
              W_COEF     => W_COEF,
618
              W_FRAC     => W_FRAC,
619
              SOSGAIN_EN => SOSGAIN_EN)
620
            port map (
621
              ClkxCI  => ClkxCI,
622
              RstxRI  => RstxRP,
623
              DatxDI  => DatWiresxS(I-1),
624
              StrbxSI => StrbWiresxS(I-1),
625
              DatxDO  => SOSDatxS,
626
              StrbxSO => SOSStrbxS,
627
              b0xDI   => CoeffRamxDP(I)(0),
628
              b1xDI   => CoeffRamxDP(I)(1),
629
              b2xDI   => CoeffRamxDP(I)(2),
630
              a1xDI   => CoeffRamxDP(I)(3),
631
              a2xDI   => CoeffRamxDP(I)(4),
632
              gxDI    => CoeffRamxDP(I)(5));
633
        end generate OutputSection;
634
      end generate CascadeSections;
635
    end generate MoreSec;
636
  end generate UsePipelineCore;
637
 
638
  -- The non-pipelined, FSM-controlled cores are used:
639
  NoUsePipelineCore : if USE_PIPELINE_CORE = false generate
640
 
641
    -- Only a single SOS; Connect it directly to input/output
642
    SingleSec : if NUM_SEC = 1 generate
643
      SingleSOS : sos_core_df1_reuse
644
        generic map (
645
          W_DAT      => W_SECT_DAT,
646
          W_COEF     => W_COEF,
647
          W_FRAC     => W_FRAC,
648
          SOSGAIN_EN => SOSGAIN_EN)
649
        port map (
650
          ClkxCI  => ClkxCI,
651
          RstxRI  => RstxRP,
652
          DatxDI  => InputDatLSxDP,
653
          StrbxSI => InputStrbLSxSP,
654
          DatxDO  => SOSDatxS,
655
          StrbxSO => SOSStrbxS,
656
          b0xDI   => CoeffRamxDP(0)(0),
657
          b1xDI   => CoeffRamxDP(0)(1),
658
          b2xDI   => CoeffRamxDP(0)(2),
659
          a1xDI   => CoeffRamxDP(0)(3),
660
          a2xDI   => CoeffRamxDP(0)(4),
661
          gxDI    => CoeffRamxDP(0)(5));
662
    end generate SingleSec;
663
 
664
    -- Two cascaded SOS; Connected in series
665
    DualSec : if NUM_SEC = 2 generate
666
      InputSOS : sos_core_df1_reuse
667
        generic map (
668
          W_DAT      => W_SECT_DAT,
669
          W_COEF     => W_COEF,
670
          W_FRAC     => W_FRAC,
671
          SOSGAIN_EN => SOSGAIN_EN)
672
        port map (
673
          ClkxCI  => ClkxCI,
674
          RstxRI  => RstxRP,
675
          DatxDI  => InputDatLSxDP,
676
          StrbxSI => InputStrbLSxSP,
677
          DatxDO  => DatWiresxS(0),
678
          StrbxSO => StrbWiresxS(0),
679
          b0xDI   => CoeffRamxDP(0)(0),
680
          b1xDI   => CoeffRamxDP(0)(1),
681
          b2xDI   => CoeffRamxDP(0)(2),
682
          a1xDI   => CoeffRamxDP(0)(3),
683
          a2xDI   => CoeffRamxDP(0)(4),
684
          gxDI    => CoeffRamxDP(0)(5));
685
 
686
      OutSOS : sos_core_df1_reuse
687
        generic map (
688
          W_DAT      => W_SECT_DAT,
689
          W_COEF     => W_COEF,
690
          W_FRAC     => W_FRAC,
691
          SOSGAIN_EN => SOSGAIN_EN)
692
        port map (
693
          ClkxCI  => ClkxCI,
694
          RstxRI  => RstxRP,
695
          DatxDI  => DatWiresxS(0),
696
          StrbxSI => StrbWiresxS(0),
697
          DatxDO  => SOSDatxS,
698
          StrbxSO => SOSStrbxS,
699
          b0xDI   => CoeffRamxDP(1)(0),
700
          b1xDI   => CoeffRamxDP(1)(1),
701
          b2xDI   => CoeffRamxDP(1)(2),
702
          a1xDI   => CoeffRamxDP(1)(3),
703
          a2xDI   => CoeffRamxDP(1)(4),
704
          gxDI    => CoeffRamxDP(1)(5));
705
    end generate DualSec;
706
 
707
    -- More than 2 SOS sections; there is an input, middle and output section.
708
    -- Wired into a cascade
709
    MoreSec : if NUM_SEC > 2 generate
710
      CascadeSections : for I in 0 to NUM_SEC-1 generate
711
        InputSection : if I = 0 generate
712
          InputSOS : sos_core_df1_reuse
713
            generic map (
714
              W_DAT      => W_SECT_DAT,
715
              W_COEF     => W_COEF,
716
              W_FRAC     => W_FRAC,
717
              SOSGAIN_EN => SOSGAIN_EN)
718
            port map (
719
              ClkxCI  => ClkxCI,
720
              RstxRI  => RstxRP,
721
              DatxDI  => InputDatLSxDP,
722
              StrbxSI => InputStrbLSxSP,
723
              DatxDO  => DatWiresxS(I),
724
              StrbxSO => StrbWiresxS(I),
725
              b0xDI   => CoeffRamxDP(I)(0),
726
              b1xDI   => CoeffRamxDP(I)(1),
727
              b2xDI   => CoeffRamxDP(I)(2),
728
              a1xDI   => CoeffRamxDP(I)(3),
729
              a2xDI   => CoeffRamxDP(I)(4),
730
              gxDI    => CoeffRamxDP(I)(5));
731
        end generate InputSection;
732
 
733
        MiddleSections : if I > 0 and I < NUM_SEC-1 generate
734
          MidSOS : sos_core_df1_reuse
735
            generic map (
736
              W_DAT      => W_SECT_DAT,
737
              W_COEF     => W_COEF,
738
              W_FRAC     => W_FRAC,
739
              SOSGAIN_EN => SOSGAIN_EN)
740
            port map (
741
              ClkxCI  => ClkxCI,
742
              RstxRI  => RstxRP,
743
              DatxDI  => DatWiresxS(I-1),
744
              StrbxSI => StrbWiresxS(I-1),
745
              DatxDO  => DatWiresxS(I),
746
              StrbxSO => StrbWiresxS(I),
747
              b0xDI   => CoeffRamxDP(I)(0),
748
              b1xDI   => CoeffRamxDP(I)(1),
749
              b2xDI   => CoeffRamxDP(I)(2),
750
              a1xDI   => CoeffRamxDP(I)(3),
751
              a2xDI   => CoeffRamxDP(I)(4),
752
              gxDI    => CoeffRamxDP(I)(5));
753
        end generate MiddleSections;
754
 
755
        OutputSection : if I = NUM_SEC-1 generate
756
          OutSOS : sos_core_df1_reuse
757
            generic map (
758
              W_DAT      => W_SECT_DAT,
759
              W_COEF     => W_COEF,
760
              W_FRAC     => W_FRAC,
761
              SOSGAIN_EN => SOSGAIN_EN)
762
            port map (
763
              ClkxCI  => ClkxCI,
764
              RstxRI  => RstxRP,
765
              DatxDI  => DatWiresxS(I-1),
766
              StrbxSI => StrbWiresxS(I-1),
767
              DatxDO  => SOSDatxS,
768
              StrbxSO => SOSStrbxS,
769
              b0xDI   => CoeffRamxDP(I)(0),
770
              b1xDI   => CoeffRamxDP(I)(1),
771
              b2xDI   => CoeffRamxDP(I)(2),
772
              a1xDI   => CoeffRamxDP(I)(3),
773
              a2xDI   => CoeffRamxDP(I)(4),
774
              gxDI    => CoeffRamxDP(I)(5));
775
        end generate OutputSection;
776
      end generate CascadeSections;
777
    end generate MoreSec;
778
  end generate NoUsePipelineCore;
779
 
780
end Behavioral;

powered by: WebSVN 2.1.0

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