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

Subversion Repositories viirf

[/] [viirf/] [trunk/] [src/] [sos_cascaded_top.vhd] - Rev 2

Compare with Previous | Blame | View Log

--------------------------------------------------------------------------------------------------------------
-- MIT License
--  
-- Copyright (c) 2017 Mario Mauerer
--  
-- Permission is hereby granted, free of charge, to any person obtaining a copy
-- of this software and associated documentation files (the "Software"), to deal
-- in the Software without restriction, including without limitation the rights
-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-- copies of the Software, and to permit persons to whom the Software is
-- furnished to do so, subject to the following conditions:
-- 
-- The above copyright notice and this permission notice shall be included in all
-- copies or substantial portions of the Software.
-- 
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-- SOFTWARE.
--
--------------------------------------------------------------------------------------------------------------
-- VHDL Naming Convention:
-- http://dz.ee.ethz.ch/en/information/hdl-help/vhdl-naming-conventions.html
--------------------------------------------------------------------------------------------------------------
--
-- VIIRF - Versatile IIR Filter
-- sos_cascaded_top.vhd
--
-- This is the filter's top-level file.
-- It applies the input gain, connects the direct-form 1 SOS/biquads in series, and applies
-- the output gain, if enabled.
--
-- Note: DatxDO is only valid when StrbxSO = '1'! The data can change
-- inbetween. 
--
-- The filter coefficients are provided to this unit via a generic coefficient
-- interface comprising the following signals. The coefficient are then stored in a
-- RAM (no vendor-specific constructs used). 
--
-- SectAddrxDI:
--      Address of the SOS/biquad for which the coefficients are provided.
--      Range: 0-NUM_SEC. Maximum allowable NUM_SEC: 255.
--      If SectAddrxDI = NUM_SEC and CoeffAddrxDI = 6, the filter's final
--      output gain is addressed. 
-- CoeffAddrxDI:
--      Address of the selected SOS coefficient. Range: 0-6. Coefficient mapping:
--      0 ==> b0
--      1 ==> b1
--      2 ==> b2
--      3 ==> a1
--      4 ==> a2
--      5 ==> g
--      6 ==> FinalGain (Can only be written if SectAddrxDI=NUM_SEC)
-- CoeffDatxDI:
--      Coefficient data of the addressed coefficient
-- CoeffValidxSI:
--      If set to high, data and addresses are valid and the coefficient data
--      is stored in an internal RAM. 
-- 
-- Generics/Configuration:
--
-- NUM_SEC:
--      Number of cascaded biquad sections to include. Max value: 255
-- W_DAT_INPUT:
--      Width of (signed) input data vector
-- GAIN_INPUT:
--      Filter input gain. Must be a power of two (left-shifts). Usable for
--      bit-extension / precision increase. If not used: set to 1.
-- W_SECT_DAT:
--      Width of SOS data path / width of SOS inputs/outputs. 
-- W_COEF:
--      Overall coefficient width (bits)
-- W_FRAC:
--      Fraction length of the coefficients (bits). Together with W_COEF, this
--      defines the Q-Notation of the quantized coefficients.
--      E.g., for Q1.15, set W_COEF=16 and W_FRAC=15.
-- SOSGAIN_EN:
--      Bool, if set to true, the output-gain stage of the SOS is generated / included
-- FINALGAIN_EN:
--      Bool, if set to true, the final filter output-gain stage is generated /
--      included
-- W_DAT_OUTPUT:
--      Width of the (signed) output data vector. Data is saturated to this
--      vector width.
-- W_DAT_INTF:
--      Width of the (std_logic_vector) address and data vectors of the generic
--      coefficient data interface.
-- USE_PIPELINE_CORE:
--      Bool, if set to true, the pipelined SOS core is used (more resource
--      usage, but higher clock rate possible). If set to false, the reuse-core
--      is utilized, which uses a single multiplier and a state-machine to
--      control the data flow.
 
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.NUMERIC_STD.all;
use IEEE.math_real.all;
 
 
entity sos_cascaded_top is
  generic(
    NUM_SEC           : integer := 27;
    W_DAT_INPUT       : integer := 16;
    GAIN_INPUT        : integer := 4;
    W_SECT_DAT        : integer := 23;
    W_COEF            : integer := 18;
    W_FRAC            : integer := 16;
    SOSGAIN_EN        : boolean := false;
    FINALGAIN_EN      : boolean := true;
    W_DAT_OUTPUT      : integer := 32;
    W_DAT_INTF        : integer := 32;
    USE_PIPELINE_CORE : boolean := true
    );
  port (
    ClkxCI        : in  std_logic;      -- Clock input
    RstxRI        : in  std_logic;      -- Reset input, active high
    -- Filter Data:
    DatxDI        : in  signed(W_DAT_INPUT-1 downto 0);  -- Input data
    StrbxSI       : in  std_logic;      -- Input strobe
    -- Output data - Only valid with StrbxSO!
    DatxDO        : out signed(W_DAT_OUTPUT-1 downto 0);
    -- Output strobe - Indicates validity of DatxDO                                 
    StrbxSO       : out std_logic;
    -- Coefficient Configuration Interface: Description: See above
    SectAddrxDI   : in  std_logic_vector(W_DAT_INTF-1 downto 0);
    CoeffAddrxDI  : in  std_logic_vector(W_DAT_INTF-1 downto 0);
    CoeffDatxDI   : in  std_logic_vector(W_DAT_INTF-1 downto 0);
    CoeffValidxSI : in  std_logic
    );
end sos_cascaded_top;
 
architecture Behavioral of sos_cascaded_top is
 
-----------------------------------------------------------------------------
-- Components
-----------------------------------------------------------------------------
 
  -- This core is the pipelined core optimized for high clock rates.
  -- This comes at the cost of heavier multiplier usage. 
  component sos_core_df1 is
    generic (
      W_DAT      : integer;
      W_COEF     : integer;
      W_FRAC     : integer;
      SOSGAIN_EN : boolean);
    port (
      ClkxCI  : in  std_logic;
      RstxRI  : in  std_logic;
      DatxDI  : in  signed(W_DAT-1 downto 0);
      StrbxSI : in  std_logic;
      DatxDO  : out signed(W_DAT-1 downto 0);
      StrbxSO : out std_logic;
      b0xDI   : in  signed(W_COEF-1 downto 0);
      b1xDI   : in  signed(W_COEF-1 downto 0);
      b2xDI   : in  signed(W_COEF-1 downto 0);
      a1xDI   : in  signed(W_COEF-1 downto 0);
      a2xDI   : in  signed(W_COEF-1 downto 0);
      gxDI    : in  signed(W_COEF-1 downto 0));
  end component sos_core_df1;
 
 
  -- This core uses a state-machine arount a single multiplier.
  -- Due to this additional logic around the multiplier, its clock frequency is
  -- more limited than the fully pipelined implementation of the core. 
  component sos_core_df1_reuse is
    generic (
      W_DAT      : integer;
      W_COEF     : integer;
      W_FRAC     : integer;
      SOSGAIN_EN : boolean);
    port (
      ClkxCI  : in  std_logic;
      RstxRI  : in  std_logic;
      DatxDI  : in  signed(W_DAT-1 downto 0);
      StrbxSI : in  std_logic;
      DatxDO  : out signed(W_DAT-1 downto 0);
      StrbxSO : out std_logic;
      b0xDI   : in  signed(W_COEF-1 downto 0);
      b1xDI   : in  signed(W_COEF-1 downto 0);
      b2xDI   : in  signed(W_COEF-1 downto 0);
      a1xDI   : in  signed(W_COEF-1 downto 0);
      a2xDI   : in  signed(W_COEF-1 downto 0);
      gxDI    : in  signed(W_COEF-1 downto 0));
  end component sos_core_df1_reuse;
 
-----------------------------------------------------------------------------
-- Signal Declarations
-----------------------------------------------------------------------------
 
  -------------
  -- Constants:
  -------------
  -- Constants for the filter coefficient interface:
  -- Width of addresses for sections and coefficients of coefficient
  -- config interface. This is hardcoded.
  constant W_SECT_ADDR   : integer := 8;  -- Allows 255 sections
  constant W_COEFF_ADDR  : integer := 3;  -- A range from 0 - 6 is required
  -- Number of coefficients per section: 6 for SOS. (b0, b1, b2, a1, a2, g).
  -- This is fixed by the direct-form 1 implementation.
  constant NUM_COEF_SECT : integer := 6;
 
  -- Number of left-shifts required for filter input gain / bit extension.
  -- Note: GAIN_INPUT has to be a power of two, otherwise, the gain will not be
  -- what's expected...
  constant NUM_INPUT_LSHIFT  : integer                                       := integer(ceil(log2(real(GAIN_INPUT))));
  -- Vector to hold the expanded bits:
  constant INPUT_EXPAND_VECT : std_logic_vector(NUM_INPUT_LSHIFT-1 downto 0) := (others => '0');
 
  -- Values for output saturation. Two's complement min and max values, defined
  -- using bit-masks instead of integers, as W_DAT_OUTPUT can be > 32 bit.
  constant SAT_OUT_POS : signed(W_DAT_OUTPUT-1 downto 0) := (W_DAT_OUTPUT-1 => '0', others => '1');
  constant SAT_OUT_NEG : signed(W_DAT_OUTPUT-1 downto 0) := (W_DAT_OUTPUT-1 => '1', others => '0');
 
  -----------
  -- Signals:
  -----------
 
  -- Coefficient interface registers and signals:
  signal SectAddrxDN, SectAddrxDP     : std_logic_vector(W_DAT_INTF-1 downto 0) := (others => '0');
  signal CoeffAddrxDN, CoeffAddrxDP   : std_logic_vector(W_DAT_INTF-1 downto 0) := (others => '0');
  signal CoeffDatxDN, CoeffDatxDP     : std_logic_vector(W_DAT_INTF-1 downto 0) := (others => '0');
  signal CoeffValidxSN, CoeffValidxSP : std_logic                               := '0';
  signal SectAddrxS                   : unsigned(W_SECT_ADDR-1 downto 0)        := (others => '0');
  signal CoeffAddrxS                  : unsigned(W_COEFF_ADDR-1 downto 0)       := (others => '0');
 
  -- Coefficient registers/RAM: This stores the filter coefficients of each section.
  -- Each section has its own set of registers:
  type COEFREG_TYPE is array (NUM_COEF_SECT-1 downto 0) of signed(W_COEF-1 downto 0);
  type SECTREGS_TYPE is array (NUM_SEC-1 downto 0) of COEFREG_TYPE;
  -- RAM to store the 6 coefficients of each section.
  signal CoeffRamxDN, CoeffRamxDP   : SECTREGS_TYPE             := (others => (others => (others => '0')));
  -- Final output gain register. This exists only once per filter.
  signal FinalGainxDN, FinalGainxDP : signed(W_COEF-1 downto 0) := (others => '0');
 
  -- Connection wires between the series-connected second-order sections.
  -- One less than NUM_SEC required:
  type STRBWIRE_TYPE is array (NUM_SEC-2 downto 0) of std_logic;
  type DATWIRE_TYPE is array (NUM_SEC-2 downto 0) of signed(W_SECT_DAT-1 downto 0);
  signal StrbWiresxS : STRBWIRE_TYPE := (others => '0');
  signal DatWiresxS  : DATWIRE_TYPE  := (others => (others => '0'));
 
  -- Various registers/signals:
  signal RstxRN, RstxRP                 : std_logic                      := '0';
  signal InputDatxDN, InputDatxDP       : signed(W_DAT_INPUT-1 downto 0) := (others => '0');
  signal InputStrbxSN, InputStrbxSP     : std_logic                      := '0';
  -- Register for holding the left-shifted input signal. Bit-Expanded to
  -- W_SECT_DAT. This is input into the first SOS.
  signal InputDatLSxDN, InputDatLSxDP   : signed(W_SECT_DAT-1 downto 0)  := (others => '0');
  signal InputStrbLSxSN, InputStrbLSxSP : std_logic                      := '0';
  -- Outputs from the last SOS. We don't register this since there is directly
  -- a register at the output of the SOS-core.
  signal SOSDatxS                       : signed(W_SECT_DAT-1 downto 0)  := (others => '0');
  signal SOSStrbxS                      : std_logic                      := '0';
 
 
-----------------------------------------------------------------------------
begin  -- Behavioral
-----------------------------------------------------------------------------
 
-----------------------------------------------------------------------------
-- Wiring
-----------------------------------------------------------------------------
  -- Registering of the coefficient interface for route-timing relaxation
  CoeffAddrxDN  <= CoeffAddrxDI;
  SectAddrxDN   <= SectAddrxDI;
  CoeffDatxDN   <= CoeffDatxDI;
  CoeffValidxSN <= CoeffValidxSI;
 
  -- For internal use: Crop the address vectors to a shorter length.
  -- Potentially reduces routing delays.
  CoeffAddrxS <= unsigned(CoeffAddrxDP(W_COEFF_ADDR-1 downto 0));
  SectAddrxS  <= unsigned(SectAddrxDP(W_SECT_ADDR-1 downto 0));
 
  -- Local reset, for better timing if filter is (area-wise) large.
  -- This also resets the cascaded sections.
  RstxRN <= RstxRI;
 
  -- Data input register: For timing relaxation
  InputDatxDN  <= DatxDI;
  InputStrbxSN <= StrbxSI;
 
  -- Apply the Input-Gain and expand the bit-width for the following biquad sections:
  InputDatLSxDN  <= resize(signed(std_logic_vector(InputDatxDP) & INPUT_EXPAND_VECT), W_SECT_DAT);
  -- Also carry the strobe forward:
  InputStrbLSxSN <= InputStrbxSP;
 
-----------------------------------------------------------------------------
-- Processes
-----------------------------------------------------------------------------
 
  -- Reads the coefficients from the coefficient data interface
  -- and stores them to the coefficient RAM.
  CoeffWrite : process(CoeffAddrxS, CoeffDatxDP, CoeffRamxDP, CoeffValidxSP,
                       FinalGainxDP, SectAddrxS)
  begin
    -- Default Assignments:
    CoeffRamxDN  <= CoeffRamxDP;
    FinalGainxDN <= FinalGainxDP;
    -- Only write when valid = 1:
    if CoeffValidxSP = '1' then
      -- Write the regular section's coefficients:
      if SectAddrxS <= NUM_SEC-1 and CoeffAddrxS <= 5 then
        CoeffRamxDN(to_integer(SectAddrxS))(to_integer(CoeffAddrxS)) <= resize(signed(CoeffDatxDP), W_COEF);
      -- Write the final output gain of the filter:
      elsif SectAddrxS = NUM_SEC and CoeffAddrxS = 6 then
        FinalGainxDN <= resize(signed(CoeffDatxDP), W_COEF);
      end if;
    end if;
  end process CoeffWrite;
 
  -- Only create / generate the final output multiplier if it's actually enabled.
  -- This saves resources and latency.
  -- The signals defined in this block are not visible outside this
  -- generate-statement, hence there is a clocking-process here, too.
  -- The required latency for the strobe-signal is 4
  GenerateFinalMul : if FINALGAIN_EN = true generate
    constant W_MUL                              : integer                                       := W_COEF + W_SECT_DAT;
    constant W_RS                               : integer                                       := W_MUL - W_FRAC;
    signal gRegxDN, gRegxDP                     : signed(W_MUL-1 downto 0)                      := (others => '0');
    signal ShiftGainOutxDN, ShiftGainOutxDP     : signed(W_MUL-1 downto 0)                      := (others => '0');
    signal ShiftGainOutRSxDN, ShiftGainOutRSxDP : signed(W_RS-1 downto 0)                       := (others => '0');
    signal OutMulxDN, OutMulxDP                 : signed(W_DAT_OUTPUT-1 downto 0)               := (others => '0');
    -- Number of latency-cycles required for the strobe-output, if the final
    -- gain is used:
    constant NUM_CYC_DEL_STRB                   : integer                                       := 4;
    -- Strobe-shift register: The input strobe is shifted "through" this unit:
    signal StrbShiftxSN, StrbShiftxSP           : std_logic_vector(NUM_CYC_DEL_STRB-1 downto 0) := (others => '0');
  begin
 
    -- This process manages the section's output gain and saturation:
    FinalGain : process(FinalGainxDP, SOSDatxS, ShiftGainOutxDP, gRegxDP,
                        shiftGainOutRSxDP)
    begin
      -- Apply the final gain:
      gRegxDN           <= SOSDatxS * FinalGainxDP;
      -- Output divider: Get rid of the gain due to the integer algebra (2^W_FRAC):
      ShiftGainOutxDN   <= shift_right(gRegxDP, W_FRAC);
      -- Resize to a smaller vector for less routing delay for the upcoming saturation:
      ShiftGainOutRSxDN <= resize(ShiftGainOutxDP, W_RS);
 
      -- Output Saturation:
      if ShiftGainOutRSxDP > SAT_OUT_POS then
        OutMulxDN <= SAT_OUT_POS;
      elsif ShiftGainOutRSxDP < SAT_OUT_NEG then
        OutMulxDN <= SAT_OUT_NEG;
      else
        OutMulxDN <= resize(shiftGainOutRSxDP, W_DAT_OUTPUT);
      end if;
    end process FinalGain;
 
    -- The core's data output is the one where the final output gain has been applied to:
    DatxDO <= OutMulxDP;
 
    -- Delay the input strobe according to the latency of the core:
    StrobeShiftOutGain : process(SOSStrbxS,
                                 StrbShiftxSP(NUM_CYC_DEL_STRB-2 downto 0))
    begin
      StrbShiftxSN(0)                           <= SOSStrbxS;
      StrbShiftxSN(NUM_CYC_DEL_STRB-1 downto 1) <= StrbShiftxSP(NUM_CYC_DEL_STRB-2 downto 0);
    end process StrobeShiftOutGain;
 
    -- Strobe output:
    StrbxSO <= StrbShiftxSP(NUM_CYC_DEL_STRB-1);
 
    --The flip-flops needed if the output gain is used:
    FF_FinalMul : process (ClkxCI)
    begin
      if ClkxCI'event and ClkxCI = '1' then
        if RstxRI = '1' then
          gRegxDP           <= (others => '0');
          ShiftGainOutxDP   <= (others => '0');
          ShiftGainOutRSxDP <= (others => '0');
          OutMulxDP         <= (others => '0');
          StrbShiftxSP      <= (others => '0');
        else
          gRegxDP           <= gRegxDN;
          ShiftGainOutxDP   <= ShiftGainOutxDN;
          ShiftGainOutRSxDP <= ShiftGainOutRSxDN;
          OutMulxDP         <= OutMulxDN;
          StrbShiftxSP      <= StrbShiftxSn;
        end if;
      end if;
    end process FF_FinalMul;
 
  end generate;
 
 
  -- If the final filter output gain is not used: simply saturate the
  -- SOS-output to the output width of the filter.  
  -- The required latency for the strobe-signal is 1
  GenerateNoFinalMul : if FINALGAIN_EN = false generate
 
    signal OutSatxDN, OutSatxDP       : signed(W_DAT_OUTPUT-1 downto 0)               := (others => '0');
    -- Number of latency-cycles required for the strobe-output, if the final
    -- gain is used:
    constant NUM_CYC_DEL_STRB         : integer                                       := 1;
    -- Strobe-shift register: The input strobe is shifted "through" this unit:
    signal StrbShiftxSN, StrbShiftxSP : std_logic_vector(NUM_CYC_DEL_STRB-1 downto 0) := (others => '0');
  begin
 
    -- Saturation:
    OutSat : process(SOSDatxS)
    begin
      if SOSDatxS > SAT_OUT_POS then
        OutSatxDN <= SAT_OUT_POS;
      elsif SOSDatxS < SAT_OUT_NEG then
        OutSatxDN <= SAT_OUT_NEG;
      else
        OutSatxDN <= resize(SOSDatxS, W_DAT_OUTPUT);
      end if;
    end process OutSat;
 
    -- The core's data output is now saturated:
    DatxDO <= OutSatxDP;
 
    -- Delay the input strobe according to the latency of the core:
    StrobeShiftOutGain : process(SOSStrbxS,
                                 StrbShiftxSP(NUM_CYC_DEL_STRB-2 downto 0))
    begin
      StrbShiftxSN(0)                           <= SOSStrbxS;
      StrbShiftxSN(NUM_CYC_DEL_STRB-1 downto 1) <= StrbShiftxSP(NUM_CYC_DEL_STRB-2 downto 0);
    end process StrobeShiftOutGain;
 
    -- Strobe output:
    StrbxSO <= StrbShiftxSP(NUM_CYC_DEL_STRB-1);
 
    --The flip-flops needed if there is no final output gain:
    FF_NoFinalMul : process (ClkxCI)
    begin
      if ClkxCI'event and ClkxCI = '1' then
        if RstxRI = '1' then
          OutSatxDP    <= (others => '0');
          StrbShiftxSP <= (others => '0');
        else
          OutSatxDP    <= OutSatxDN;
          StrbShiftxSP <= StrbShiftxSN;
        end if;
      end if;
    end process FF_NoFinalMul;
 
  end generate;
 
 
  -- The local reset flip-flop:
  RstFF : process (ClkxCI)
  begin
    if ClkxCI'event and ClkxCI = '1' then
      RstxRP <= RstxRN;
    end if;
  end process RstFF;
 
 
  -- The flip-flops:
  FF : process (ClkxCI)
  begin
    if ClkxCI'event and ClkxCI = '1' then
      if RstxRP = '1' then
        SectAddrxDP    <= (others => '0');
        CoeffAddrxDP   <= (others => '0');
        CoeffDatxDP    <= (others => '0');
        CoeffValidxSP  <= '0';
        CoeffRamxDP    <= (others => (others => (others => '0')));
        FinalGainxDP   <= (others => '0');
        InputDatxDP    <= (others => '0');
        InputStrbxSP   <= '0';
        InputDatLSxDP  <= (others => '0');
        InputStrbLSxSP <= '0';
      else
        SectAddrxDP    <= SectAddrxDN;
        CoeffAddrxDP   <= CoeffAddrxDN;
        CoeffDatxDP    <= CoeffDatxDN;
        CoeffValidxSP  <= CoeffValidxSN;
        CoeffRamxDP    <= CoeffRamxDN;
        FinalGainxDP   <= FinalGainxDN;
        InputDatxDP    <= InputDatxDN;
        InputStrbxSP   <= InputStrbxSN;
        InputDatLSxDP  <= InputDatLSxDN;
        InputStrbLSxSP <= InputStrbLSxSN;
      end if;
    end if;
  end process FF;
 
 
-----------------------------------------------------------------------------
-- Instances
-----------------------------------------------------------------------------
 
  -- In the following, the SOS instances are cascaded.
  -- Both is done either for the pipelined or the reuse-core.
  -- Furthermore, if there is only one, two or more sections, the wiring is
  -- slightly different, as there are or are no middle or output sections.
 
  -- The pipelined cores are used:
  UsePipelineCore : if USE_PIPELINE_CORE = true generate
 
    -- Only a single SOS; Connect it directly to input/output
    SingleSec : if NUM_SEC = 1 generate
      SingleSOS : sos_core_df1
        generic map (
          W_DAT      => W_SECT_DAT,
          W_COEF     => W_COEF,
          W_FRAC     => W_FRAC,
          SOSGAIN_EN => SOSGAIN_EN)
        port map (
          ClkxCI  => ClkxCI,
          RstxRI  => RstxRP,
          DatxDI  => InputDatLSxDP,
          StrbxSI => InputStrbLSxSP,
          DatxDO  => SOSDatxS,
          StrbxSO => SOSStrbxS,
          b0xDI   => CoeffRamxDP(0)(0),
          b1xDI   => CoeffRamxDP(0)(1),
          b2xDI   => CoeffRamxDP(0)(2),
          a1xDI   => CoeffRamxDP(0)(3),
          a2xDI   => CoeffRamxDP(0)(4),
          gxDI    => CoeffRamxDP(0)(5));
    end generate SingleSec;
 
    -- Two cascaded SOS; Connected in series
    DualSec : if NUM_SEC = 2 generate
      InputSOS : sos_core_df1
        generic map (
          W_DAT      => W_SECT_DAT,
          W_COEF     => W_COEF,
          W_FRAC     => W_FRAC,
          SOSGAIN_EN => SOSGAIN_EN)
        port map (
          ClkxCI  => ClkxCI,
          RstxRI  => RstxRP,
          DatxDI  => InputDatLSxDP,
          StrbxSI => InputStrbLSxSP,
          DatxDO  => DatWiresxS(0),
          StrbxSO => StrbWiresxS(0),
          b0xDI   => CoeffRamxDP(0)(0),
          b1xDI   => CoeffRamxDP(0)(1),
          b2xDI   => CoeffRamxDP(0)(2),
          a1xDI   => CoeffRamxDP(0)(3),
          a2xDI   => CoeffRamxDP(0)(4),
          gxDI    => CoeffRamxDP(0)(5));
 
      OutSOS : sos_core_df1
        generic map (
          W_DAT      => W_SECT_DAT,
          W_COEF     => W_COEF,
          W_FRAC     => W_FRAC,
          SOSGAIN_EN => SOSGAIN_EN)
        port map (
          ClkxCI  => ClkxCI,
          RstxRI  => RstxRP,
          DatxDI  => DatWiresxS(0),
          StrbxSI => StrbWiresxS(0),
          DatxDO  => SOSDatxS,
          StrbxSO => SOSStrbxS,
          b0xDI   => CoeffRamxDP(1)(0),
          b1xDI   => CoeffRamxDP(1)(1),
          b2xDI   => CoeffRamxDP(1)(2),
          a1xDI   => CoeffRamxDP(1)(3),
          a2xDI   => CoeffRamxDP(1)(4),
          gxDI    => CoeffRamxDP(1)(5));
    end generate DualSec;
 
    -- More than 2 SOS sections; there is an input, middle and output section.
    -- Wired into a cascade
    MoreSec : if NUM_SEC > 2 generate
      CascadeSections : for I in 0 to NUM_SEC-1 generate
        InputSection : if I = 0 generate
          InputSOS : sos_core_df1
            generic map (
              W_DAT      => W_SECT_DAT,
              W_COEF     => W_COEF,
              W_FRAC     => W_FRAC,
              SOSGAIN_EN => SOSGAIN_EN)
            port map (
              ClkxCI  => ClkxCI,
              RstxRI  => RstxRP,
              DatxDI  => InputDatLSxDP,
              StrbxSI => InputStrbLSxSP,
              DatxDO  => DatWiresxS(I),
              StrbxSO => StrbWiresxS(I),
              b0xDI   => CoeffRamxDP(I)(0),
              b1xDI   => CoeffRamxDP(I)(1),
              b2xDI   => CoeffRamxDP(I)(2),
              a1xDI   => CoeffRamxDP(I)(3),
              a2xDI   => CoeffRamxDP(I)(4),
              gxDI    => CoeffRamxDP(I)(5));
        end generate InputSection;
 
        MiddleSections : if I > 0 and I < NUM_SEC-1 generate
          MidSOS : sos_core_df1
            generic map (
              W_DAT      => W_SECT_DAT,
              W_COEF     => W_COEF,
              W_FRAC     => W_FRAC,
              SOSGAIN_EN => SOSGAIN_EN)
            port map (
              ClkxCI  => ClkxCI,
              RstxRI  => RstxRP,
              DatxDI  => DatWiresxS(I-1),
              StrbxSI => StrbWiresxS(I-1),
              DatxDO  => DatWiresxS(I),
              StrbxSO => StrbWiresxS(I),
              b0xDI   => CoeffRamxDP(I)(0),
              b1xDI   => CoeffRamxDP(I)(1),
              b2xDI   => CoeffRamxDP(I)(2),
              a1xDI   => CoeffRamxDP(I)(3),
              a2xDI   => CoeffRamxDP(I)(4),
              gxDI    => CoeffRamxDP(I)(5));
        end generate MiddleSections;
 
        OutputSection : if I = NUM_SEC-1 generate
          OutSOS : sos_core_df1
            generic map (
              W_DAT      => W_SECT_DAT,
              W_COEF     => W_COEF,
              W_FRAC     => W_FRAC,
              SOSGAIN_EN => SOSGAIN_EN)
            port map (
              ClkxCI  => ClkxCI,
              RstxRI  => RstxRP,
              DatxDI  => DatWiresxS(I-1),
              StrbxSI => StrbWiresxS(I-1),
              DatxDO  => SOSDatxS,
              StrbxSO => SOSStrbxS,
              b0xDI   => CoeffRamxDP(I)(0),
              b1xDI   => CoeffRamxDP(I)(1),
              b2xDI   => CoeffRamxDP(I)(2),
              a1xDI   => CoeffRamxDP(I)(3),
              a2xDI   => CoeffRamxDP(I)(4),
              gxDI    => CoeffRamxDP(I)(5));
        end generate OutputSection;
      end generate CascadeSections;
    end generate MoreSec;
  end generate UsePipelineCore;
 
  -- The non-pipelined, FSM-controlled cores are used:
  NoUsePipelineCore : if USE_PIPELINE_CORE = false generate
 
    -- Only a single SOS; Connect it directly to input/output
    SingleSec : if NUM_SEC = 1 generate
      SingleSOS : sos_core_df1_reuse
        generic map (
          W_DAT      => W_SECT_DAT,
          W_COEF     => W_COEF,
          W_FRAC     => W_FRAC,
          SOSGAIN_EN => SOSGAIN_EN)
        port map (
          ClkxCI  => ClkxCI,
          RstxRI  => RstxRP,
          DatxDI  => InputDatLSxDP,
          StrbxSI => InputStrbLSxSP,
          DatxDO  => SOSDatxS,
          StrbxSO => SOSStrbxS,
          b0xDI   => CoeffRamxDP(0)(0),
          b1xDI   => CoeffRamxDP(0)(1),
          b2xDI   => CoeffRamxDP(0)(2),
          a1xDI   => CoeffRamxDP(0)(3),
          a2xDI   => CoeffRamxDP(0)(4),
          gxDI    => CoeffRamxDP(0)(5));
    end generate SingleSec;
 
    -- Two cascaded SOS; Connected in series
    DualSec : if NUM_SEC = 2 generate
      InputSOS : sos_core_df1_reuse
        generic map (
          W_DAT      => W_SECT_DAT,
          W_COEF     => W_COEF,
          W_FRAC     => W_FRAC,
          SOSGAIN_EN => SOSGAIN_EN)
        port map (
          ClkxCI  => ClkxCI,
          RstxRI  => RstxRP,
          DatxDI  => InputDatLSxDP,
          StrbxSI => InputStrbLSxSP,
          DatxDO  => DatWiresxS(0),
          StrbxSO => StrbWiresxS(0),
          b0xDI   => CoeffRamxDP(0)(0),
          b1xDI   => CoeffRamxDP(0)(1),
          b2xDI   => CoeffRamxDP(0)(2),
          a1xDI   => CoeffRamxDP(0)(3),
          a2xDI   => CoeffRamxDP(0)(4),
          gxDI    => CoeffRamxDP(0)(5));
 
      OutSOS : sos_core_df1_reuse
        generic map (
          W_DAT      => W_SECT_DAT,
          W_COEF     => W_COEF,
          W_FRAC     => W_FRAC,
          SOSGAIN_EN => SOSGAIN_EN)
        port map (
          ClkxCI  => ClkxCI,
          RstxRI  => RstxRP,
          DatxDI  => DatWiresxS(0),
          StrbxSI => StrbWiresxS(0),
          DatxDO  => SOSDatxS,
          StrbxSO => SOSStrbxS,
          b0xDI   => CoeffRamxDP(1)(0),
          b1xDI   => CoeffRamxDP(1)(1),
          b2xDI   => CoeffRamxDP(1)(2),
          a1xDI   => CoeffRamxDP(1)(3),
          a2xDI   => CoeffRamxDP(1)(4),
          gxDI    => CoeffRamxDP(1)(5));
    end generate DualSec;
 
    -- More than 2 SOS sections; there is an input, middle and output section.
    -- Wired into a cascade
    MoreSec : if NUM_SEC > 2 generate
      CascadeSections : for I in 0 to NUM_SEC-1 generate
        InputSection : if I = 0 generate
          InputSOS : sos_core_df1_reuse
            generic map (
              W_DAT      => W_SECT_DAT,
              W_COEF     => W_COEF,
              W_FRAC     => W_FRAC,
              SOSGAIN_EN => SOSGAIN_EN)
            port map (
              ClkxCI  => ClkxCI,
              RstxRI  => RstxRP,
              DatxDI  => InputDatLSxDP,
              StrbxSI => InputStrbLSxSP,
              DatxDO  => DatWiresxS(I),
              StrbxSO => StrbWiresxS(I),
              b0xDI   => CoeffRamxDP(I)(0),
              b1xDI   => CoeffRamxDP(I)(1),
              b2xDI   => CoeffRamxDP(I)(2),
              a1xDI   => CoeffRamxDP(I)(3),
              a2xDI   => CoeffRamxDP(I)(4),
              gxDI    => CoeffRamxDP(I)(5));
        end generate InputSection;
 
        MiddleSections : if I > 0 and I < NUM_SEC-1 generate
          MidSOS : sos_core_df1_reuse
            generic map (
              W_DAT      => W_SECT_DAT,
              W_COEF     => W_COEF,
              W_FRAC     => W_FRAC,
              SOSGAIN_EN => SOSGAIN_EN)
            port map (
              ClkxCI  => ClkxCI,
              RstxRI  => RstxRP,
              DatxDI  => DatWiresxS(I-1),
              StrbxSI => StrbWiresxS(I-1),
              DatxDO  => DatWiresxS(I),
              StrbxSO => StrbWiresxS(I),
              b0xDI   => CoeffRamxDP(I)(0),
              b1xDI   => CoeffRamxDP(I)(1),
              b2xDI   => CoeffRamxDP(I)(2),
              a1xDI   => CoeffRamxDP(I)(3),
              a2xDI   => CoeffRamxDP(I)(4),
              gxDI    => CoeffRamxDP(I)(5));
        end generate MiddleSections;
 
        OutputSection : if I = NUM_SEC-1 generate
          OutSOS : sos_core_df1_reuse
            generic map (
              W_DAT      => W_SECT_DAT,
              W_COEF     => W_COEF,
              W_FRAC     => W_FRAC,
              SOSGAIN_EN => SOSGAIN_EN)
            port map (
              ClkxCI  => ClkxCI,
              RstxRI  => RstxRP,
              DatxDI  => DatWiresxS(I-1),
              StrbxSI => StrbWiresxS(I-1),
              DatxDO  => SOSDatxS,
              StrbxSO => SOSStrbxS,
              b0xDI   => CoeffRamxDP(I)(0),
              b1xDI   => CoeffRamxDP(I)(1),
              b2xDI   => CoeffRamxDP(I)(2),
              a1xDI   => CoeffRamxDP(I)(3),
              a2xDI   => CoeffRamxDP(I)(4),
              gxDI    => CoeffRamxDP(I)(5));
        end generate OutputSection;
      end generate CascadeSections;
    end generate MoreSec;
  end generate NoUsePipelineCore;
 
end Behavioral;
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

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