aboutsummaryrefslogtreecommitdiffstats
path: root/testsuite/gna/issue263/mac.vhdl
blob: ff05cb5ccf134bdbcb589da5c5c70d7a4dcafe8d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
library ieee;
use ieee.std_logic_1164.all, ieee.fixed_pkg.all;
use ieee.math_complex.all;

entity mac is 
    port( clk, reset : in std_ulogic;
          x_real : in u_sfixed(0 downto -15);-- real and imaginary part of the two input data sequences
          x_imag : in u_sfixed(0 downto -15);
          y_real : in u_sfixed(0 downto -15);
          y_imag : in u_sfixed(0 downto -15);
          s_real : out u_sfixed(0 downto -15); --real and imaginary parts of accumulated sum
          s_imag : out u_sfixed(0 downto -15);
          ovf : out std_ulogic); --overflow flag
end entity mac;


-- Behavioral model of MAC algorithm allows for focus on the algorithm without being distracted 
-- by other details at this erly design stage.

architecture behavioral of mac is 
    signal x_complex, y_complex, s_complex : complex;

begin
    x_complex <= ( to_real(x_real), to_real(x_imag) );
    y_complex <= ( to_real(y_real), to_real(y_imag) );

    behavior : process (clk) is
        variable input_x, input_y : complex := (0.0, 0.0);
        variable real_part_product_1, real_part_product_2,
                 imag_part_product_1, imag_part_product_2 : real := 0.0;   
        variable product, sum : complex := (0.0, 0.0);
        variable real_accumulator_ovf,
                 imag_accumulator_ovf : boolean := false;
    begin
        if rising_edge(clk) then
            -- Work from the end of the pipeline back to the start,
            -- so as not to overwrite previosu results from the pipeline
            -- registers before they are even used. 

            -- Update accumulator and generate outputs. 
            if reset then
                sum := (0.0, 0.0);
                real_accumulator_ovf := false;
                imag_accumulator_ovf := false;
            else
                sum := product + sum;
                real_accumulator_ovf := real_accumulator_ovf 
                                        or sum.re < -16.0
                                        or sum.re >= +16.0;
                imag_accumulator_ovf := imag_accumulator_ovf 
                                        or sum.im < -16.0
                                        or sum.im >= +16.0;
            end if;
            s_complex <= sum;
            ovf <= '1'; 
            -- ovf <= '1' when (real_accumulator_ovf or imag_accumulator_ovf
            --                 or sum.re < -1.0 or sum.re >= +1.0
            --                 or sum.im < -1.0 or sum.im >= +1.0 ) else '0';
            -- Update product registers
            product.re := real_part_product_1 - real_part_product_2;
            product.im := imag_part_product_1 + imag_part_product_2;

            -- Update partial product registers
            -- (actually with the full product).
            real_part_product_1 := input_x.re * input_y.re;
            real_part_product_2 := input_x.im * input_y.im;
            imag_part_product_1 := input_x.re * input_y.re;
            imag_part_product_2 := input_x.im * input_y.im;

            -- Update input registers using MAC inputs
            input_x := x_complex;
            input_y := y_complex;
        end if;
    end process behavior;
    s_real <= to_sfixed(s_complex.re, s_real);
    s_imag <= to_sfixed(s_complex.im, s_imag);
end architecture behavioral;