-- -----------------------------------------------------------
-- 
-- 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:      A-Law Companding
-- 
-- Description:
-- The model describes the A-law companding scheme that is
-- used for signal compression. The input voltage must be 
-- between -VMAX and VMAX.
-- 
-- Literature:
-- 
-- Dependencies: 
-- -----------------------------------------------------------
-- Logical Library         Design unit
-- -----------------------------------------------------------
-- IEEE_proposed           ELECTRICAL_SYSTEMS
-- IEEE                    MATH_REAL
-- -----------------------------------------------------------
--
-- Source:
-- compress.vhd
-- -----------------------------------------------------------

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

entity COMPRESS is
    generic (K    : POSITIVE  := 1;  -- index for A array, MIN: 1, MAX: 6
             VMAX : REAL      := 1.0 -- maximum voltage [V], MIN: >0.0
            );
    port (terminal INP  : ELECTRICAL; -- controlling terminal
          terminal OUTP : ELECTRICAL  -- output terminal
         );
begin
    assert K <= 6
      report "ERROR: 1 <= K <= 6 required."
      severity ERROR;

    assert VMAX > 0.0
      report "ERROR: VMAX > 0.0 required."
      severity ERROR;
end entity COMPRESS;   

   
architecture V1 of COMPRESS is

 quantity VIN  across INP;
 quantity VOUT across IOUT through OUTP;
 constant AK  : REAL_VECTOR (1 to 6)
       := (1.0, 5.36, 14.77, 36.85, 87.56, 201.84);
 constant A   : REAL  := Ak(k);

begin

 if ABS(VIN/VMAX) < 1.0/A use
  VOUT == A/(1.0+LOG(A))*vin;
 else
  VOUT == VMAX*SIGN(VIN/VMAX)*(1.0+LOG(A*ABS(VIN/VMAX)))/(1.0+LOG(A));
 end use;

 assert VIN'ABOVE(-VMAX) and not VIN'ABOVE(VMAX)
   report "WARNING: VIN out of range."
   severity WARNING;

end architecture V1;
