-- -----------------------------------------------------------
-- 
-- Additional material to the book
-- Modeling and Simulation for RF System Design
-- 
--
-- THIS MODEL IS LICENSED TO YOU "AS IT IS" AND WITH NO WARRANTIES, 
-- EXPRESSED OR IMPLIED. THE AUTHORS SPECIFICALLY DISCLAIM ALL IMPLIED 
-- WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
-- THEY MUST NOT HAVE ANY RESPONSIBILITY FOR ANY DAMAGES, FINANCIAL OR
-- LEGAL CLAIMS WHATEVER.
-- -----------------------------------------------------------

-- Name:     Lowpass filter
-- 
-- Description:
-- This part describes the architecture BHV_RF of the lowpass filter.
-- It uses the package FILTER to compute the filter coefficients.
-- Filters of grade 1 to 6 are available. They are implemented using
-- the 'DOT attribute. A simpler implementation would use the
-- LTF statement.
-- ATTENTION: we observed problems with version 4.0_3.1 of ADMS
--            when using the doubled 'DOT'DOT attribute as in
--            this model
--
-- Literature:
-- 
--
-- Dependencies: 
-- -----------------------------------------------------------
-- Logical Library         Design unit
-- -----------------------------------------------------------
-- IEEE_proposed           ELECTRICAL_SYSTEMS
-- IEEE                    MATH_REAL
-- WORK                    FILTER
-- -----------------------------------------------------------
--
-- Source:
-- lowpass_bhv.vhd
-- -----------------------------------------------------------

library IEEE,IEEE_proposed;
  use IEEE.MATH_REAL.all;
  use IEEE_proposed.ELECTRICAL_SYSTEMS.all;
  use WORK.FILTER.all;

entity LOWPASS_FILTER is
  generic (GAIN   : REAL    := 0.0;    -- maximum amplifier gain [dB]
           FG     : REAL    := 1.0;    -- cut-off frequency [Hz], MIN: >0.0
           GRAD   : INTEGER := 1;      -- grade of filter [-], MIN: >0, MAX: <7
           RIN    : REAL    := 50.0;   -- input resistance [Ohm], MIN: >0.0
           ROUT   : REAL    := 50.0    -- output resistance [Ohm], MIN: >0.0
	   );
  port (terminal INP  : ELECTRICAL;    -- positive input pin
	terminal INN  : ELECTRICAL;    -- negative input pin
	terminal OUTP : ELECTRICAL;    -- positive output pin
	terminal OUTN : ELECTRICAL     -- negative output pin
	);
begin

  assert FG > 0.0
    report "fg > 0.0 required"
    severity error;

  assert GRAD > 0 and GRAD < 7
    report "grad has to be between 1 and 6"
    severity error;

  assert RIN > 0.0  
    report "rin > 0.0 required."
    severity error;

  assert ROUT > 0.0  
    report "rout > 0.0 required."
    severity error;


end entity LOWPASS_FILTER;

architecture BHV_RF of LOWPASS_FILTER is

  constant A0   : REAL    := 2.0*SQRT(10**(GAIN/10.0)*ROUT/RIN);
  constant NU   : INTEGER := (GRAD+1)/2;
  constant OMG  : REAL    := MATH_2_PI*FG;
  constant OMG2 : REAL    := OMG*OMG;
  constant A    : REAL_VECTOR (1 to NU) := LOWPASS_BUTTERWORTH_A (GRAD);  
  constant B    : REAL_VECTOR (1 to NU) := LOWPASS_BUTTERWORTH_B (GRAD); 
  terminal OUTM: ELECTRICAL;
  quantity VIN   across IIN   through INP  to INN;
  quantity VROUT across IROUT through OUTP to OUTM;
  quantity VO    across IOUT  through OUTM to OUTN;
  quantity Q0, Q1, Q2, Q3      : REAL;

begin

  -- input impedance
  VIN == RIN*IIN;

  -- output impedance
  VROUT == ROUT*IOUT;
  
  -- filter function
  Q0  == VIN;
  case GRAD use
          when 1 => Q1 + A(1)/OMG*Q1'DOT + B(1)/OMG2*Q1'DOT'DOT == Q0;
                    VO == A0*Q1; 
                    Q2 == 0.0; Q3 == 0.0; 

          when 2 => Q1 + A(1)/OMG*Q1'DOT + B(1)/OMG2*Q1'DOT'DOT == Q0;
                    VO == A0*Q1;
                    Q2 == 0.0; Q3 == 0.0; 

    
          when 3 => Q1 + A(1)/OMG*Q1'DOT + B(1)/OMG2*Q1'DOT'DOT == Q0;
                    Q2 + A(2)/OMG*Q2'DOT + B(2)/OMG2*Q2'DOT'DOT == Q1;
                    VO == A0*Q2;
                    Q3 == 0.0; 

          when 4 => Q1 + A(1)/OMG*Q1'DOT + B(1)/OMG2*Q1'DOT'DOT == Q0;
                    Q2 + A(2)/OMG*Q2'DOT + B(2)/OMG2*Q2'DOT'DOT == Q1;
                    VO == A0*Q2;
                    Q3 == 0.0; 
                       
          when 5 => Q1 + A(1)/OMG*Q1'DOT + B(1)/OMG2*Q1'DOT'DOT == Q0;
                    Q2 + A(2)/OMG*Q2'DOT + B(2)/OMG2*Q2'DOT'DOT == Q1;
                    Q3 + A(3)/OMG*Q3'DOT + B(3)/OMG2*Q3'DOT'DOT == Q2;
                    VO == A0*Q3;
  
     when others => Q1 + A(1)/OMG*Q1'DOT + B(1)/OMG2*Q1'DOT'DOT == Q0;
                    Q2 + A(2)/OMG*Q2'DOT + B(2)/OMG2*Q2'DOT'DOT == Q1;
                    Q3 + A(3)/OMG*Q3'DOT + B(3)/OMG2*Q3'DOT'DOT == Q2;
                    VO == A0*Q3;
  end case;

end architecture BHV_RF;

