VHDL Source Code of Mac in behavior level
--------------------------------
-- VHDL code for Complex MAC
-- (multiplier accumulators)
-- at BEHAVIOUR LEVEL
--------------------------------


--##############################
--#Library of Complex MAC
--##############################
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_arith.all;

LIBRARY bitlib;
USE bitlib.bit_pack.all;


--##############################
--#Entity of Complex MAC
--##############################
ENTITY c_mac_behv IS
PORT (
  clk, clr : IN bit;                           -- input
  x_real   : IN bit_vector(15 downto 0);       -- input
  x_imag   : IN bit_vector(15 downto 0);       -- input
  y_real   : IN bit_vector(15 downto 0);       -- input
  y_imag   : IN bit_vector(15 downto 0);       -- input

  s_real   : OUT bit_vector(15 downto 0);      -- output
  s_imag   : OUT bit_vector(15 downto 0);      -- output
  ovf      : OUT bit);                         -- output
END c_mac_behv;



--###########################################################
--# Implementing using the complex MAC at behaviour level
--###########################################################
ARCHITECTURE behv OF c_mac_behv IS

--######################
--#Function Declaration
--######################
-- Function vec_2s_complement (converts a bit vector to its 2's complement vector)
FUNCTION vec_2s_complement(vec1: bit_vector)
        RETURN bit_vector IS
VARIABLE vec_tmp1 : bit_vector(vec1'length-1 downto 0);
VARIABLE retval   : bit_vector(vec1'length-1 downto 0);
BEGIN   
  loop1: FOR i IN 0 TO vec1'length-1 LOOP
           vec_tmp1(i) := NOT vec1(i);
  END LOOP loop1;

  retval:= int2vec(vec2int(vec_tmp1)+1,vec1'length);
  RETURN retval;
END vec_2s_complement;


-- Function get the fraction part of a real 
FUNCTION fp_fraction(fp_in: real)
        RETURN real IS
VARIABLE flag     : boolean := false ;
VARIABLE fp_out   : real := 0.0;
BEGIN   
  IF fp_in > 0.0 THEN
        flag := true;
  END IF;
  
  fp_out := fp_in;
  
  loop1: WHILE TRUE LOOP
  --FOR i IN 0 TO 16 LOOP
           IF (fp_out >= -1.0) AND (fp_out <1.0) THEN
              RETURN fp_out;
           END IF;
           
           IF flag THEN
              fp_out := fp_out - 1.0;
           ELSE
              fp_out := fp_out + 1.0;
           END IF;
           
  END LOOP loop1;

END fp_fraction;



--######################
--#Procedure Declaration
--######################
--the procedure convert a fp vector(-1<= and <1, the highest bit is sign bit)
--to a real number
PROCEDURE vector2fp ( 
  vec1_in: IN bit_vector; 
  SIGNAL fp_out : OUT real
) IS
VARIABLE retval: real := 0.0;
VARIABLE base  : real := 1.0;
VARIABLE flg   : boolean := false;
VARIABLE tmp_vec: bit_vector(vec1_in'length-1 downto 0);
BEGIN
        IF vec1_in(vec1_in'length-1)='1' THEN
                flg := true;   
                tmp_vec := vec_2s_complement(vec1_in);
                IF tmp_vec(tmp_vec'length-1)='1' THEN
                   retval := 1.0;
                END IF;
        ELSE
                tmp_vec := vec1_in;
        END IF;
        
        
        FOR i IN tmp_vec'length-2 DOWNTO 0 LOOP
                base := base * 0.5;
                IF (tmp_vec(i)='1') THEN
                        retval := retval + base;
                END IF;
        END LOOP;
        
        IF flg THEN
                retval := -retval;
        END IF;
        
        fp_out <= retval;
END vector2fp;


--the procedure convert a real number to a 
--fp vector(-1<= and <1, the highest bit is sign bit)
PROCEDURE fp2vector ( 
  SIGNAL fp_in: IN real ;
  n_in: IN integer;  -- vector length
  SIGNAL vec_out : OUT bit_vector
) IS

VARIABLE base  : real := 1.0;
VARIABLE flg   : boolean := false;
VARIABLE tmp_real: real := 0.0;
VARIABLE tmp_vec: bit_vector(n_in-1 downto 0);
BEGIN
        IF fp_in < 0.0 THEN
                flg := true;
        END IF;

        tmp_real := abs(fp_in);
        tmp_vec(n_in-1) := '0';
        FOR i IN n_in-2 DOWNTO 0 LOOP
                base := base * 0.5;
                IF tmp_real >= base THEN
                   tmp_real := tmp_real - base;
                   tmp_vec(i) := '1';
                ELSE 
                   tmp_vec(i) := '0';
                END IF;
        END LOOP;
        
        IF flg THEN
            vec_out <= vec_2s_complement(tmp_vec);
        ELSE 
            vec_out <= tmp_vec;
        END IF;

END fp2vector;

--######################
--#Signal Declaration
--######################
SIGNAL  x_real_fp : real := 0.0;
SIGNAL  x_imag_fp : real := 0.0;
SIGNAL  y_real_fp : real := 0.0;
SIGNAL  y_imag_fp : real := 0.0;

SIGNAL  s_real_fp : real := 0.0;
SIGNAL  s_imag_fp : real := 0.0;

BEGIN

  x_real_converter : vector2fp (x_real, x_real_fp);
  x_imag_converter : vector2fp (x_imag, x_imag_fp);
  y_real_converter : vector2fp (y_real, y_real_fp);
  y_imag_converter : vector2fp (y_imag, y_imag_fp);

  PROCESS(clk, clr)
  variable real_product1: real := 0.0;
  variable real_product2: real := 0.0;
  variable imag_product1: real := 0.0;
  variable imag_product2: real := 0.0;
  variable real_result  : real := 0.0;
  variable imag_result  : real := 0.0;
  
  variable s_real_sum_fp: real := 0.0;
  variable s_imag_sum_fp: real := 0.0;

  variable acc_ovf : boolean := false;
  variable sum_ovf : boolean := false;
  BEGIN

    -- assume it changes state on rising edge

    IF clr = '1' THEN 
                s_real_fp <= 0.0;  
                s_imag_fp <= 0.0;
                ovf <= '0' ;
                s_real_sum_fp := 0.0;
                s_imag_sum_fp := 0.0;
                sum_ovf := false;
    ELSIF rising_edge(clk) THEN
        -- calculate the partial products
        real_product1 := x_real_fp * y_real_fp;
        real_product2 := x_imag_fp * y_imag_fp;
        imag_product1 := x_real_fp * y_imag_fp;
        imag_product2 := x_imag_fp * y_real_fp;
        
        -- calculate the multiplication results
        real_result := real_product1 - real_product2;
        imag_result := imag_product1 + imag_product2;
        
        -- calculate the summation
        s_real_sum_fp := s_real_sum_fp + real_result;
        s_imag_sum_fp := s_imag_sum_fp + imag_result;

        s_real_fp <= fp_fraction(s_real_sum_fp) AFTER 1 ns;
        s_imag_fp <= fp_fraction(s_imag_sum_fp) AFTER 1 ns;
        
        -- calculate the ovf
        acc_ovf := (s_real_sum_fp >= +1.0) OR (s_real_sum_fp < -1.0) OR (s_imag_sum_fp >= +1.0) OR (s_imag_sum_fp < -1.0);
        IF sum_ovf = false THEN
           sum_ovf := (s_real_sum_fp >= +16.0) OR (s_real_sum_fp < -16.0) OR (s_imag_sum_fp >= +16.0) OR (s_imag_sum_fp < -16.0);
        END IF;
        IF acc_ovf OR sum_ovf THEN
                ovf <= '1' AFTER 1 ns;
        ELSE
                ovf <= '0' AFTER 1 ns;
        END IF;         
    END IF;   
  END PROCESS;
  
  s_real_convertor : fp2vector(s_real_fp, 16, s_real);
  s_imag_convertor : fp2vector(s_imag_fp, 16, s_imag);
END behv;

------------------------------------
-- end of VHDL code for Complex MAC
-- (multiplier accumulators)
-- at BEHAVIOUR LEVEL
------------------------------------


Go back to My Homepage